#申请原创#@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型数据更真实。
|