#申请原创#@21小跑堂 我们在测试完其内部外设之后,我们可以连接其外围设备进行其他外设功能测试,今天我就连接一款NB-IOT模块,进行阿里云的通信测试。我们使用安信可的ec616模块。模块通过AT指令进行操作,完成阿里云的接入也很简单,下面就一起看下吧。 模块通过串口1接入到开发板的串口2(PA2,PA3)上。 之后工程模板我通过自己新建了一个。 风格上就是按照我自己的风格进行设置的,主要在Drives目录下添加上我们外部设备的驱动。 整体程序还是按照之前的LED灯的基础上修改的。因为其最基础,所以我们可以按照我们方式添加东西。 #include "usart.h"
#include "EC616S.h"
#pragma import(__use_no_semihosting)
//标准库需要支持的函数
struct __FILE
{
int handle;
};
FILE __stdout;
//定义_sys_exit()以避免工作在半主机状态
void _sys_exit(int x)
{
x = x;
}
//重定义fputc函数
//这个需要根据MCU和我们希望printf从哪个串口输出来确认 __WAIT_TODO__
int fputc(int ch, FILE *f)
{
//注意:USART_FLAG_TXE是检查发送缓冲区是否为空,这个要在发送前检查,检查这个提议提高发送效率,但是在休眠的时候可能导致最后一个字符丢失
//USART_FLAG_TC是检查发送完成标志,这个在发送后检查,这个不会出现睡眠丢失字符问题,但是效率低(发送过程中发送缓冲区已经为空了,可以接收下一个数据了,但是因为要等待发送完成,所以效率低)
//不要两个一起用,一起用效率最低
//循环等待直到发送缓冲区为空(TX Empty)此时可以发送数据到缓冲区
while (USART_GetFlagStatus(USART1, USART_FLAG_TXDE) == RESET)
{}
USART_SendData(USART1, (uint8_t) ch);
/* 循环等待直到发送结束*/
while (USART_GetFlagStatus(USART1, USART_FLAG_TXC) == RESET){}
return ch;
}
void uart2_Init(u32 bound)//串口2 引脚为PA2(Tx) PA3(Rx)
{
USART_InitType USART_InitStructure;
GPIO_InitType GPIO_InitStructure;
NVIC_InitType NVIC_InitStructure;
RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_USART2, ENABLE);
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE); //使能指定端口时钟
GPIO_InitStructure.Pin = GPIO_PIN_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure); //初始化GPIO
GPIO_InitStructure.Pin = GPIO_PIN_3;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure); //初始化GPIO
//Usart2 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//USART2配置
USART_InitStructure.BaudRate = bound; //设置串口波特率
USART_InitStructure.WordLength = USART_WL_8B; //字长为8
USART_InitStructure.StopBits = USART_STPB_1; //1个停止位
USART_InitStructure.Parity = USART_PE_NO; //无奇偶校验
USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE; //无流控
USART_InitStructure.Mode = USART_MODE_RX | USART_MODE_TX; //收发模式
USART_Init(USART2, &USART_InitStructure); //配置USART参数
USART_ConfigInt(USART2, USART_INT_RXDNE|USART_INT_IDLEF, ENABLE);//配置了接收中断和总线空闲中断
USART_Enable(USART2, ENABLE); //使能USART
}
void USART2_IRQHandler(void)
{
u8 ucCh;
if(USART_GetFlagStatus( USART2, USART_FLAG_RXDNE ) != RESET )
{
ucCh = USART_ReceiveData( USART2 );
// USART_SendData(USART3,ucCh);
if(EC616S_Fram_Record_Struct .InfBit .FramLength < ( RX_BUF_MAX_LEN - 1 ) )
{
EC616S_Fram_Record_Struct .Data_RX_BUF[ EC616S_Fram_Record_Struct .InfBit .FramLength ++ ] = ucCh;
}
}
if( USART_GetFlagStatus( USART2, USART_FLAG_IDLEF ) == SET ) //如果总线空闲
{
EC616S_Fram_Record_Struct .InfBit .FramFinishFlag = 1;
ucCh = USART_ReceiveData( USART2 ); //由软件序列清除中断标志位(先读USART_SR,然后读USART_DR)
// USART_SendData(USART3,ucCh);
}
}
void uart1_Init(u32 bound)//串口1 引脚为PB10(Tx) PB11(Rx)
{
GPIO_InitType GPIO_InitStructure;
USART_InitType USART_InitStructure;
NVIC_InitType NVIC_InitStructure;
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_USART1, ENABLE);
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE);
GPIO_InitStructure.Pin = GPIO_PIN_9; //PB10
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIO_PIN_10;//PB11
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);//初始化GPIO
//Usart3 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;//抢占优先级0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //响应优先级0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //USART_IRQn通道使能
NVIC_Init(&NVIC_InitStructure); //初始化NVIC
//USART3 配置
USART_InitStructure.BaudRate = bound;//波特率
USART_InitStructure.WordLength = USART_WL_8B;//数据长度
USART_InitStructure.StopBits = USART_STPB_1;//停止位1
USART_InitStructure.Parity = USART_PE_NO;//校验位无
USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;//硬件流控制无
USART_InitStructure.Mode = USART_MODE_RX | USART_MODE_TX; //使能串口的接收和发送功能
USART_Init(USART1, &USART_InitStructure); //初始化串口
USART_ConfigInt(USART1, USART_INT_RXDNE|USART_INT_IDLEF, ENABLE);//配置了接收中断和总线空闲中断
USART_Enable(USART1, ENABLE); //串口外设使能
}
void USART1_IRQHandler( void )
{
u8 ucCh;
if(USART_GetFlagStatus( USART1, USART_FLAG_RXDNE ) != RESET )
{
ucCh = USART_ReceiveData( USART1 );
if(EC616S_Fram_Record_Struct .InfBit .FramLength < ( RX_BUF_MAX_LEN - 1 ) )
{
//留最后一位做结束位
EC616S_Fram_Record_Struct .Data_RX_BUF[ EC616S_Fram_Record_Struct .InfBit .FramLength ++ ] = ucCh;
}
}
if( USART_GetFlagStatus( USART1, USART_FLAG_IDLEF ) == SET ) //如果总线空闲
{
EC616S_Fram_Record_Struct .InfBit .FramFinishFlag = 1;
ucCh = USART_ReceiveData( USART1); //由软件序列清除中断标志位(先读USART_SR,然后读USART_DR)
}
}
这部分是串口代码,里面主要是放置了初始化串口设备的功能。以及把串口1作为printf输出进行了重定向,也就是其中的fputc()函数。之后就是两个串口初始化,串口1作为打印设备是应为其接在了我们仿真器口上,由仿真器提供虚拟串口可以直接在电脑上查看数据。 之后就是每个串口的中断服务函数编写,利用了串口的空闲中断接受不定长数据。 在EC616S中就是我们模块的AT指令功能。需要对接阿里云的AT指令都列出来了。 之后就需要在阿里云物联网平台上创建我们需要的设备接入信息。 具体步骤如上。 我们选择需要的产品功能。联网方式是蜂窝(2g,3g,4g)选项。 之后创建设备。查看设备的信息。 如上,这些都是要在后面代码中使用的。 如图,到这里我们再看下底层代码。 我们需要修改AccessCloud.c文件,复制就好了。 之后就是测试数据了。 使用sprintf连接。完成数据上云工作。 此次还是模拟,下次我们接入真实的传感器,获得真实值上传。 修改成float型数据更真实。
|