sos博 发表于 2019-7-13 11:01:45

HAL怎么写串口接收函数?

我想实现的就是,能收到其他设备发来的命令比如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有点懵。


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


sos博 发表于 2019-7-13 11:07:28

我写了2个函数
void send_str(uint8_t *cc)
{
      HAL_UART_Transmit_DMA(&huart1, cc, (strlen(cc)));
}

uint8_t* rev_str()
{
      uint8_t *cc;
      HAL_UART_Receive_DMA(&huart1, cc, (strlen(cc)));
      return cc;
}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可以参考呀:

sos博 发表于 2019-7-13 12:32:24

本帖最后由 sos博 于 2019-7-13 13:05 编辑

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


看了你文章,想问一个太低端的问题。。。
如果在main的while里面这样写,我这个写法肯定不对,但是我的意思你应该明白了。
if(rx_flag==1)
                {
                        switch(UART1_Rx_Buffer)//HAL_UART_Receive_DMA(&huart1, UART1_Rx_Buffer, DMA_RX_BUFFER_SIZE);
                        {
                              case "openled": HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);break;
                              case "closeled": HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);break;
                              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

确实不太方便,我使用的时候,把他这个改掉了。用的环形队列接收数据。

mikecai 发表于 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 查询或定时中断即可晓得是否结束了 串口不定长数据接收, 实在还不行,加换行或回车符 检查啊。

sos博 发表于 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
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()函数可以用于复杂情况(不建议用)。


sos博 发表于 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吗?比如见到空格就算一次接收完成。
我现在真的什么都不记得了。记得以前的标准库是可以实现的。
页: [1] 2
查看完整版本: HAL怎么写串口接收函数?