• STM32+USART+DMA+EC600N调试


    STM32+USART+DMA+EC600N调试

    用到的工具:

    ​ 公用的TCP/IP服务器:http://tongxinmao.com

    串口调试助手:sscom33

    网络调试助手:通信猫调试软件

    1.USART+DMA调试

    1. 在stm32Cube中,打开DMA发送中断和接收中断,打开usart全局中断。

    2. 主要调试功能:(1)使用DMA发送固定长度数据给串口,(2)使用DMA接收不定长度帧数据。

    3. (1)利用DMA传输,发送固定大小数据

      HAL_UART_Transmit(&huart1,BigTxData,2,100);
      
      • 1

      换成

      HAL_UART_Transmit_DMA(&huart1,BigTxData,1023);
      
      • 1

      包装代码如下:

      //串口1的DMA发送
      void UART1_TX_DMA_Send(uint8_t *buffer, uint16_t length)
      {
          //等待上一次的数据发送完毕
      	while(HAL_DMA_GetState(&hdma_usart1_tx) != HAL_DMA_STATE_READY);
          //while(__HAL_DMA_GET_COUNTER(&hdma_usart1_tx));
      	
          //关闭DMA
          __HAL_DMA_DISABLE(&hdma_usart1_tx);
      
          //开始发送数据
          HAL_UART_Transmit_DMA(&huart1, buffer, length);
      }
      
      //串口1的DMA发送printf
      void Debug_printf(const char *format, ...)
      {
      	uint32_t length = 0;
      	va_list args;
      	
      	__va_start(args, format);
      	
      	length = vsnprintf((char*)usart1_tx_buffer, sizeof(usart1_tx_buffer), (char*)format, args);
      	
      	UART1_TX_DMA_Send(usart1_tx_buffer, length);
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26

      (2)利用DMA传输,接收大小可变的数据

      利用串口空闲中断,识别一帧的数据,参考链接:

      //串口接收空闲中断
      void HAL_UART_ReceiveIdle(UART_HandleTypeDef *huart)
      {
      	//当触发了串口空闲中断
          if((__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE) != RESET)) 
          {
      
      				if(huart->Instance == USART1)
      				{
      					/* 1.清除标志 */
      					__HAL_UART_CLEAR_IDLEFLAG(huart); //清除空闲标志
      
      					/* 2.读取DMA */
      					HAL_UART_DMAStop(huart); //先停止DMA,暂停接收
      					//这里应注意数据接收不要大于 USART_DMA_RX_BUFFER_MAXIMUM
      					usart1_rx_len = USART_DMA_RX_BUFFER_MAXIMUM - (__HAL_DMA_GET_COUNTER(&hdma_usart1_rx)); //接收个数等于接收缓冲区总大小减剩余计数
      					
      					/* 3.搬移数据进行其他处理 */
      					memcpy(receive_data, usart1_rx_buffer, usart1_rx_len); 
      					usart1_rx_flag = 1; //标志已经成功接收到一包等待处理
      				}
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
    4. 注意:空闲中断结束后,记得重新开启DMA接收。

    2.EC600N调试

    EC600N-CN模块使用AT指令控制,可以使用UBS和串口模式通信。这里只研究串口模式通信过程。

    1. 指令解析

      AT+CPIN?\r\n
      查询SIM卡状态,返回1帧
      >+CPIN: READY\r\nOK\r\n
      
      AT+CREG?\r\n
      查询CS业务状态,返回1帧
      >+CREG: 0,1\r\nOK\r\n
      
      
      
      AT+CGREG?\r\n
      查询PS状态,返回1帧
      >+CGREG: 0,1\r\nOK\r\n
      
      
      AT+QICSGP=1\r\n
      查询PDP场景,场景1,返回1帧
      +QICSGP: 1,"CMIOT","","",1\r\nOK\r\n
      
      
      AT+QICSGP=1,1,"CMIOT","","",1
      配置PDP场景1,移动物联网,账号密码不用配置,在wifi中可能需要配置,暂时没有配置QoS,大数据发送可能需要配置阻塞。
      
      >\r\nOK\r\n
      
      
      AT+QIACT=1\r\n
      激活PDP场景1
      >\r\nOK\r\n
      
      
      AT+QIOPEN=1,0,"TCP",120.76.100.197,10002,0,2\r\n
      打开socket连接,透传模式。
      >CONNECT
      
      +++
      退出透传模式,返回两帧
      >OK
      >+QIURC: "recv",0
      
      ATO/r/n
      重新连接
      >CONNECT
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      1. AT执行逻辑

      每个AT指令执行成功,则继续下一条,如果本条AT指令执行失败,则重复执行,最多执行10次,

      如果10全部失败,则本轮结束,从第一条指令开始执行,如果5轮全部失败,则重新执行4G模块

      硬件初始化流程(电源复位(可跳过),4G模块复位,开机),然后继续执行AT指令;

      1. 主要程序

    ​ 使用消息地图进行顺序状态机的执行

    typedef struct 											//定义状态机结构体
    {
    	unsigned char msg_data[20];
    	
    	FUN_P fnprocess;
    	
    }Message_Item;
    /*************************消息地图*********************************/
    const static Message_Item c_tMSGMap[]  =  {
        {"ATE0\r\n",                lte_4g_protocol_default_send},			//关闭回显
        {"ATE0\r\n",                lte_4g_protocol_default_send},
        {"ATE0\r\n",                lte_4g_protocol_default_send},
        {"ATE0\r\n",                lte_4g_protocol_default_send},
        {"AT+CPIN?\r\n",            lte_4g_protocol_CPIN},							//查询SIM卡状态,返回1帧
        {"AT+CSQ\r\n",              lte_4g_protocol_CSQ},								//查询信号强度
        {"AT+CREG?\r\n",            lte_4g_protocol_CREG},							//查询CS状态,返回1帧
        {"AT+QICSGP",               lte_4g_protocol_QICSGP},            //设置APN,用户名和密码
        {"AT+QIDEACT=1\r\n",        lte_4g_protocol_default_send},          //去激活
        {"AT\r\n",                  lte_4g_protocol_default_send},			
        {"AT\r\n",                  lte_4g_protocol_default_send},
        {"AT+QIACT=1\r\n",          lte_4g_protocol_default_send},      //激活
        {"AT+QIACT?\r\n",           lte_4g_protocol_default_send},      //是否激活成功
       // {"AT+QICLOSE=0\r\n",        lte_4g_protocol_MYNETCLOSE},        //关闭socket
        {"AT+QIOPEN",               lte_4g_protocol_QIOPEN},            //创建socket
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    其中一个状态机中的发送处理函数

    unsigned char lte_4g_protocol_default_send(void)
    {
    		unsigned char success_flag=0;
    		Debug_printf("%s",c_tMSGMap[count3].msg_data);			//发送命令
    		success_flag=findStr((char *)receive_data, "OK",200);		//等待接收并检测
    				
    		memset(receive_data,'\0',sizeof(receive_data));					//清空数组
    		usart1_rx_flag=0;																				//复位空闲标志位---可以加一个判断。
    	
    		if(success_flag)				
    		return 1;
    		else
    		return 0;
    		
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    等待与查询函数

    static unsigned char findStr(char* dest,char* src,unsigned int retry_cn)
    {
        unsigned int retry = retry_cn;                   //超时时间
        unsigned char result_flag = 0;                     //查找结果
    
        while(strstr(dest,src)==0 && --retry!=0)//等待串口接收完毕或超时退出
        {
            HAL_Delay(10);
        }
    
       if(retry > 0)                           
       {
           result_flag = 1;										 //执行到这里说明一切正常, 表示查找成功
       }                      
    
       return result_flag;
    
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    3. 工程链接

    gitee:https://gitee.com/WhyIT/stm32-example

  • 相关阅读:
    JavaScript算法33- 兼具大小写的最好英文字母(leetCode:2309简单)
    node实战——koa实现文件上传
    深入理解死锁问题
    第13篇:ESP32 idf wifi联网使用SNTP同步网络时间LCD ST7920液晶屏显示
    【每日一读】CoRGi: Content-Rich Graph Neural Networks with Attention
    Docker安装Jenkins
    LazadaAPI接口解析,实现获得lazada商品评论列表
    嵌入式工程师,用好C语言这一利器的三要素
    MySQL 多表关联一对多查询实现取最新一条数据
    从零使用GAN(生成对抗网络)进行图像生成
  • 原文地址:https://blog.csdn.net/qq_21835111/article/details/127774630