你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

HAL怎么写串口接收函数?

[复制链接]
tryfly 提问时间:2019-7-13 11:01 /
我想实现的就是,能收到其他设备发来的命令比如  openled  ,然后mcu收到命令就点GPIO。

我现在的情况是:

芯片:042
库:HAL
串口方式:DMA串口收和发


我现在的问题是:
uint8_t cc[] = "hello sos";
1,可以正常发数据  使用HAL_UART_Transmit_DMA(&huart1, cc, (strlen(cc)));    //这里不知道用strlen对不对,反正我用sizeof不能读空格后面的sos。
2,我不知道接收数据函数怎么使用,HAL_UART_Receive_DMA(&huart1, cc, (strlen(cc)));
3,HAL_UART_RxCpltCallback这个串口接收完成回调函数是,收到数据后,才进这个函数吗?我在这里面放了点灯函数,结果上电灯就亮。我没给它发数据,为什么还是进到了这个函数呢?




综上,我的问题是,怎么能收到命令?我有30多条命令要接收,判断执行不同功能。
这个HAL有点懵。


谢谢好心人。自己研究好几天了也没头绪。


收藏 评论11 发布时间:2019-7-13 11:01

举报

11个回答
tryfly 回答时间:2019-7-13 11:07:28
我写了2个函数
  1. void send_str(uint8_t *cc)
  2. {
  3.         HAL_UART_Transmit_DMA(&huart1, cc, (strlen(cc)));
  4. }

  5. uint8_t* rev_str()
  6. {
  7.         uint8_t *cc;
  8.         HAL_UART_Receive_DMA(&huart1, cc, (strlen(cc)));
  9.         return cc;
  10. }
复制代码
1,把send_str放到main的while(1)里面好用,正常输出。
2,我这样弄,send_str(rev_str());   收不到我发送给mcu的数据
3,我又看人有这样的if(strcmp(rev_str(),getdown)==0)     //uint8_t getdown[] = "get_down";
没效果。

4,我不知道应该怎样收数据,来判断收到的是啥。

radio2radio 回答时间:2019-7-13 11:22:25
UART是人人都用的,建议您找一套UART收发正常的底包,然后改成自己适用的。
不能指望一条语句就搞定。

参考:
https://www.stmcu.org.cn/module/forum/thread-616613-1-1.html
https://www.stmcu.org.cn/module/forum/thread-619702-1-1.html
wenyangzeng 回答时间:2019-7-13 11:27:18
sos博 发表于 2019-7-13 11:07
我写了2个函数
1,把send_str放到main的while(1)里面好用,正常输出。
2,我这样弄,send_str(rev_str());  ...

ST官方有很多DEMO可以参考呀:
UART_Printf.rar (43.06 KB, 下载次数: 7)
tryfly 回答时间:2019-7-13 12:32:24
本帖最后由 sos博 于 2019-7-13 13:05 编辑
radio2radio 发表于 2019-7-13 11:22
UART是人人都用的,建议您找一套UART收发正常的底包,然后改成自己适用的。
不能指望一条语句就搞定。

看了你文章,想问一个太低端的问题。。。
如果在main的while里面这样写,我这个写法肯定不对,但是我的意思你应该明白了。
  1. if(rx_flag==1)
  2.                 {
  3.                         switch(UART1_Rx_Buffer)//HAL_UART_Receive_DMA(&huart1, UART1_Rx_Buffer, DMA_RX_BUFFER_SIZE);
  4.                         {
  5.                                 case "openled": HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);break;
  6.                                 case "closeled": HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);break;
  7.                                 case "temp": HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);break;
复制代码
就是怎么把指针UART1_Rx_Buffer里面的内容,变成明文?用来让我识别读出。还有switch里面case直接接 “字符串命令”,这样可以吗?
废鱼 回答时间:2019-7-13 16:22:59
确实不太方便,我使用的时候,把他这个改掉了。用的环形队列接收数据。
慎微 回答时间:2019-7-13 19:29:56
接收可用DMA, 发送就不必。DMA接收函数用一次启动即可,不必每次用callback接收到DMA;用环形DMA是好主意,可参考本论坛原创:”基于DMA循环接收的串口不定长数据处理方案“一文:  https://www.stmcu.org.cn/module/forum/thread-613418-1-57.html
再参考串口 波特率,如单字节传送时间为3 ms, 设15 ms 查询或定时中断即可晓得是否结束了 串口不定长数据接收, 实在还不行,加换行或回车符 检查啊。

评分

参与人数 1蝴蝶豆 +3 收起 理由
STMCU + 3

查看全部评分

tryfly 回答时间:2019-7-13 21:22:06
安 发表于 2019-7-13 16:22
确实不太方便,我使用的时候,把他这个改掉了。用的环形队列接收数据。

能分享一下你的串口相关的几句代码吗?感谢。
radio2radio 回答时间:2019-7-13 21:25:18
本帖最后由 radio2radio 于 2019-7-13 21:28 编辑
sos博 发表于 2019-7-13 12:32
看了你文章,想问一个太低端的问题。。。
如果在main的while里面这样写,我这个写法肯定不对,但是我的意 ...

你说的是UART接受数据的解析,如果命令少可以很简单, 如果命令很多,有可能很复杂麻烦。
关键是把逻辑搞清楚。我也不是很有经验,只能说一说我使用过的方法。

1. 把收到的字符串放入一个数组变量,也就是那个缓冲区Buffer[x]
2. 三个命令只解析前面的4个字符,open/clos/temp
3. 每当接收到4个字符,就产生一次rx_flag=1
      4. 使用memcmp(),比较是否三个命令之一,如果是就执行相应动作.
      5. 清空Buffer,rx_flag=0
6. 搞一个timeout机制,当一定的时间内,比如10ms,只收到<=3个字符,清空Buffer。

至于是用while/switch/if来做开关,看您自己的喜欢。

除了memcmp()内存比较函数,还有个strstr()函数可以用于复杂情况(不建议用)。


评分

参与人数 1蝴蝶豆 +3 收起 理由
STMCU + 3

查看全部评分

tryfly 回答时间:2019-7-13 21:34:11
radio2radio 发表于 2019-7-13 21:25
你说的是UART接受数据的解析,如果命令少可以很简单, 如果命令很多,有可能很复杂麻烦。
关键是把逻辑搞 ...

哦,我学你那个,然后把flag=1放到HAL_UART_RxCpltCallbacki里面了,我DMA_RX_BUFFER_SIZE也学习你的先写了128,然后我就发现,确实好用,现象是,必须收够128个才进入flag=1,比如我发12345678,我得发16次,凑够128个数才进入接收完成回调函数。
我想问,它能根据发来的数据自动判断是多少个DMA_RX_BUFFER_SIZE吗?比如见到空格就算一次接收完成。
我现在真的什么都不记得了。记得以前的标准库是可以实现的。
radio2radio 回答时间:2019-7-13 21:51:19
本帖最后由 radio2radio 于 2019-7-13 21:59 编辑
sos博 发表于 2019-7-13 21:34
哦,我学你那个,然后把flag=1放到HAL_UART_RxCpltCallbacki里面了,我DMA_RX_BUFFER_SIZE也学习你的先写 ...

如果不是必须,建议不使用DMA方式,中断方式的很清晰。

在DMA里面的中断处理的这一句:
    temp  = hdma_usart1_rx.Instance->CNDTR;
    rx_len1 =  BUFFER_SIZE - temp;

应该在这里搞定 rx_flag=1。

慎微 回答时间:2019-7-15 09:49:24
while loop 前一句启动 HAL_UART_Receive_DMA(&huart2,ringBuf.pBuf,ringBuf.bufSize);
while loop 中:retval = ringBufPop(&userBuf[userPrt],50-userPrt,&ringBuf,&hdma_usart2_rx);
                if(retval)  //收到数据 get responde  
                {
                        userPrt+=retval;
                        uart2PrevTick = HAL_GetTick();
                        if(userPrt > 10 ) // data respond data 1/3 buffer ,print it
                        {
                                HAL_UART_Transmit(&hlpuart1,userBuf,userPrt,10);
                                while(userPrt !=0) //clean buffer
                                {
                                        userBuf[userPrt] = 0;
                                        userPrt--;
                                }
                        }
                }
                else //idle 没收到DMA
                {
                        if (0!= userPrt)  
                        {       
                                 if((HAL_GetTick()-uart2PrevTick) >= 10) // 间隔时间大于 10ms【对9600 波特率】,那就是单条命令接收 已完成
                                 {
                                 HAL_UART_Transmit(&hlpuart1,userBuf,userPrt,10); //print receive data by hlpuart1
                                                 
                   ParseData();// 解析数据
                                        while(userPrt !=0) //clean buffer
                                        {
                                                userBuf[userPrt] = 0;
                                                userPrt--;
                                        }                                                 

                         }
                }
          }

所属标签

相似问题

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版