UART

UART

解决串口通信的warning

新手交流admin 回复了问题 • 2 人关注 • 1 个回复 • 45 次浏览 • 2019-10-14 17:26 • 来自相关话题

STM32F10x_RS485Modbus从站源程序

回复

经验分享现场总线/以太网/modbus开 发起了问题 • 1 人关注 • 0 个回复 • 83 次浏览 • 2019-10-05 11:11 • 来自相关话题

STM32 USART的RXNEIE不能置位或无法置位的原因(非QRE)

问题困惑yuan123456 回复了问题 • 2 人关注 • 1 个回复 • 223 次浏览 • 2019-08-03 21:53 • 来自相关话题

记录stm32F4discovery板利用stm32cubemx实现串口的usart_IAP功能全过程

软件教程chenlmm 回复了问题 • 26 人关注 • 21 个回复 • 10660 次浏览 • 2019-05-17 13:59 • 来自相关话题

请教使用cube 配置STM32F405RGT6 的串口 结果再输入脚PA10 USART_RX的模式选择中只有 PUSH POLL 没有INPUT

回复

问题困惑TeaCJ 回复了问题 • 1 人关注 • 2 个回复 • 294 次浏览 • 2019-04-05 11:26 • 来自相关话题

STM32L15系列IO模拟串口失败,请教

问题困惑自带腹肌的西装 回复了问题 • 2 人关注 • 4 个回复 • 350 次浏览 • 2019-03-22 10:07 • 来自相关话题

分享一个串口的使用技巧(单字节中断后续字节处理)

经验分享自带腹肌的西装 回复了问题 • 10 人关注 • 5 个回复 • 4335 次浏览 • 2019-03-19 09:28 • 来自相关话题

串口通讯莫名停止

回复

新手交流牙子男男 发起了问题 • 2 人关注 • 0 个回复 • 522 次浏览 • 2019-03-14 16:58 • 来自相关话题

关于按键和UART的问题 通过按键向串口输出不同的字符串,但是用串口软件没办法看到输出的信息

问题困惑admin 回复了问题 • 2 人关注 • 1 个回复 • 674 次浏览 • 2018-12-03 21:12 • 来自相关话题

回调函数到底是如何调用的

新手交流1533033440 回复了问题 • 3 人关注 • 2 个回复 • 2834 次浏览 • 2018-11-07 15:05 • 来自相关话题

关于stm32cube中UART串口的新库函数的一些东西理解,长久记录

经验分享風影旋新月 回复了问题 • 28 人关注 • 10 个回复 • 32633 次浏览 • 2018-08-20 16:24 • 来自相关话题

分享一个由串口uart接收命令,来动态调整tim定时器pwm模式脉冲宽度的小实验

软件教程想飞的四轴 回复了问题 • 43 人关注 • 19 个回复 • 12810 次浏览 • 2018-08-17 12:20 • 来自相关话题

stm32f407vet6 通过串口助手用错误波特率通信导致串口崩溃

问题困惑admin 回复了问题 • 2 人关注 • 2 个回复 • 786 次浏览 • 2018-02-27 19:44 • 来自相关话题

STM32F103的HAL USART很奇怪的问题

问题困惑「祭礼の蛇」 回复了问题 • 9 人关注 • 11 个回复 • 6771 次浏览 • 2017-12-01 10:26 • 来自相关话题

请教一个串口配置问题:

回复

问题困惑zhaobao511 发起了问题 • 1 人关注 • 0 个回复 • 733 次浏览 • 2017-08-18 11:32 • 来自相关话题

关于HAL库串口中断接收哪些路子 第一弹

经验分享L 发表了文章 • 11 个评论 • 5926 次浏览 • 2015-06-19 15:56 • 来自相关话题

一个串口中断搞了两周半,实在汗颜,群里也啰嗦了好多了,为了答谢给予我帮助的一些人,也为了回馈本论坛,就把这两个半周的领悟发出来,希望后来人不要再像我一样走弯路了!废话不多说,直接主题啦!
先说我的硬件平台,最常见的正点原子407开发板,一说“正点”又多想了哈!用过MX的请自动忽略第一弹,直瞅第二弹,节约你的时间。

1 .首先,打开MX,进入那一系列的配置,如图:









我的板载芯片是STM32F407ZGT6,这里自然也选407,LQFP封装,对应选择。









片子跑起来,除了电源的另一重要部分,时钟源,我的板子有外部晶振,虽然片子内部也有,但传说中外部的更精准,谁知道呢,反正我没试过,有就用呗,选外部晶振源。









串口的研究,这里不用多说,我用USART1调试,因为板子电路把USART1做成了RS232,并且都转换成了USB接口的,只要一根手机充电线就OK,总之就是简单,那就USART1吧,选择第一个异步通信。









这里要说下,调试接口,看到好多人都没选,也能跑得很happy,但是之前也试过仿真的时候遇到一些问题,还没总结原因到底是不是因为这个,但本人觉得人为定义调试方式总比片子自己判断来的靠谱吧,Maybe!我这里选得SWD调试方法。

到这里,管脚配置基本完了,进入下一步!(看到就这么个东东搞两周半,再汗颜一下)









这一步是配置时钟的,我觉得只要是这个论坛的,没有不知道的!(就是这么啃腚)之前说过要用外部晶振源,而我的外部晶振8M,这里自然要对应把其改成8M,之后就是一系列的锁相环倍频因子、锁相环倍频数之类的巴拉巴拉,串口挂在APB2上,一顿废话之后,我们要做的就是:
点选HSE外部高速,然后在点选PLLCLK倍频时钟,APB2框填那个最大的84M(额就爱最大滴),回车或任意空白单击左键,MX会帮我们搞定的。嘿嘿!










这一步是各个模块的相关配置,我们主要针对USART,NVIC里把串口的中断打勾,至于组优先和子优先就不研究了,默认0就OK!










至此,设置完毕,欢快的点那个齿轮,选择路径和开发平台,去生成代码吧,我的开发环境Keil5,就选这个了,重要提示,路径一定要是全英文字符,不然Keil要报错滴!

2 .这里,就开始说说串口了,我就喝口水,使劲罗嗦了,别嫌烦啊!
先说一个最基本的,神马是信息?(求别喷)记得信息论里大概这么个意思,有变化的的东西携带有信息,就好比我写个 1 ,它的信息量少的就是个 1,但我写个 n ,它的信息量基本就无穷大,因为我 n 是多少都可以 ,所以,我们计算机里传递信息就要搞个有复杂度,但又不能太复杂的东西,通俗点说:携带有穷信息的东东,于是,高低电平就出来了,于是,单个高低电平不满足需求,多信息位出来了,于是多信息位不好校验,接收,解析,串行协议就出来了。这么多于是,我不知道怎么解释,我也一知半解,但我觉得差不多到这里就可以了,现在说说串行协议里的几个关键词,波特率已经被老生长谈了,关于发送时间的换算也有了,我就一笔带过,我今天想说说数据位(因为它把我坑了):
常见的数据位就两种: 8位、9位,常用的数据位只有1种:8位,这里是学过微机原理人脑子里的概念,但是,实际情况是这样的8位机中: 一般是 0-8-0-0 结构,0起始位 8数据位 0奇偶校验位 0停止位=8位; 一种 1-8-0-1结构 ,1起始位 8数据位 0奇偶校验位 1停止位=10位。其他9位数据位的不研究,有兴趣的自己“吻度娘”,我们得到两个信息,
不同结构同一波特率数据量有差异;串行数据一帧,有且只会有一个8位的数据,也就是1Byte。


有以上结论,就去耍“码子”吧,打开项目,面对的是一系列系统初始化,包括串口滴(哇哈哈哈,ST真是贴心啊),看看他干了啥?找到main.c并打开,找到这一句:
`UART_HandleTypeDef huart1;` 声明一个串口结构体,用的一种面向对象的思想(别问我怎么知道是串口结构体不是其他的,不然地球不适合你),这里是个神马东东?带一下:


typedef struct
{
USART_TypeDef [i]Instance; /[/i]!< UART registers base address */

UART_InitTypeDef Init; /[i]!< UART communication parameters [/i]/

uint8_t [i]pTxBuffPtr; /[/i]!< Pointer to UART Tx transfer Buffer */

uint16_t TxXferSize; /[i]!< UART Tx Transfer size [/i]/

uint16_t TxXferCount; /[i]!< UART Tx Transfer Counter [/i]/

uint8_t [i]pRxBuffPtr; /[/i]!< Pointer to UART Rx transfer Buffer */

uint16_t RxXferSize; /[i]!< UART Rx Transfer size [/i]/

uint16_t RxXferCount; /[i]!< UART Rx Transfer Counter [/i]/

DMA_HandleTypeDef [i]hdmatx; /[/i]!< UART Tx DMA Handle parameters */

DMA_HandleTypeDef [i]hdmarx; /[/i]!< UART Rx DMA Handle parameters */

HAL_LockTypeDef Lock; /[i]!< Locking object [/i]/

__IO HAL_UART_StateTypeDef State; /[i]!< UART communication state [/i]/

__IO uint32_t ErrorCode; /[i]!< UART Error code [/i]/

}UART_HandleTypeDef;

这里强调一下,由于万恶的 “版圈法”,我的后续已不够全部写在这里,详见 《关于HAL库串口中断接收哪些路子 第二弹》,将就下吧! 查看全部
一个串口中断搞了两周半,实在汗颜,群里也啰嗦了好多了,为了答谢给予我帮助的一些人,也为了回馈本论坛,就把这两个半周的领悟发出来,希望后来人不要再像我一样走弯路了!废话不多说,直接主题啦!
先说我的硬件平台,最常见的正点原子407开发板,一说“正点”又多想了哈!用过MX的请自动忽略第一弹,直瞅第二弹,节约你的时间。

1 .首先,打开MX,进入那一系列的配置,如图:



1.png



我的板载芯片是STM32F407ZGT6,这里自然也选407,LQFP封装,对应选择。



2.png



片子跑起来,除了电源的另一重要部分,时钟源,我的板子有外部晶振,虽然片子内部也有,但传说中外部的更精准,谁知道呢,反正我没试过,有就用呗,选外部晶振源。



3.png



串口的研究,这里不用多说,我用USART1调试,因为板子电路把USART1做成了RS232,并且都转换成了USB接口的,只要一根手机充电线就OK,总之就是简单,那就USART1吧,选择第一个异步通信。



4.png



这里要说下,调试接口,看到好多人都没选,也能跑得很happy,但是之前也试过仿真的时候遇到一些问题,还没总结原因到底是不是因为这个,但本人觉得人为定义调试方式总比片子自己判断来的靠谱吧,Maybe!我这里选得SWD调试方法。

到这里,管脚配置基本完了,进入下一步!(看到就这么个东东搞两周半,再汗颜一下)



5.png



这一步是配置时钟的,我觉得只要是这个论坛的,没有不知道的!(就是这么啃腚)之前说过要用外部晶振源,而我的外部晶振8M,这里自然要对应把其改成8M,之后就是一系列的锁相环倍频因子、锁相环倍频数之类的巴拉巴拉,串口挂在APB2上,一顿废话之后,我们要做的就是:
点选HSE外部高速,然后在点选PLLCLK倍频时钟,APB2框填那个最大的84M(额就爱最大滴),回车或任意空白单击左键,MX会帮我们搞定的。嘿嘿!



6.png




这一步是各个模块的相关配置,我们主要针对USART,NVIC里把串口的中断打勾,至于组优先和子优先就不研究了,默认0就OK!



7.png




至此,设置完毕,欢快的点那个齿轮,选择路径和开发平台,去生成代码吧,我的开发环境Keil5,就选这个了,重要提示,路径一定要是全英文字符,不然Keil要报错滴!

2 .这里,就开始说说串口了,我就喝口水,使劲罗嗦了,别嫌烦啊!
先说一个最基本的,神马是信息?(求别喷)记得信息论里大概这么个意思,有变化的的东西携带有信息,就好比我写个 1 ,它的信息量少的就是个 1,但我写个 n ,它的信息量基本就无穷大,因为我 n 是多少都可以 ,所以,我们计算机里传递信息就要搞个有复杂度,但又不能太复杂的东西,通俗点说:携带有穷信息的东东,于是,高低电平就出来了,于是,单个高低电平不满足需求,多信息位出来了,于是多信息位不好校验,接收,解析,串行协议就出来了。这么多于是,我不知道怎么解释,我也一知半解,但我觉得差不多到这里就可以了,现在说说串行协议里的几个关键词,波特率已经被老生长谈了,关于发送时间的换算也有了,我就一笔带过,我今天想说说数据位(因为它把我坑了):
常见的数据位就两种: 8位、9位,常用的数据位只有1种:8位,这里是学过微机原理人脑子里的概念,但是,实际情况是这样的8位机中: 一般是 0-8-0-0 结构,0起始位 8数据位 0奇偶校验位 0停止位=8位; 一种 1-8-0-1结构 ,1起始位 8数据位 0奇偶校验位 1停止位=10位。其他9位数据位的不研究,有兴趣的自己“吻度娘”,我们得到两个信息,
不同结构同一波特率数据量有差异;串行数据一帧,有且只会有一个8位的数据,也就是1Byte。


有以上结论,就去耍“码子”吧,打开项目,面对的是一系列系统初始化,包括串口滴(哇哈哈哈,ST真是贴心啊),看看他干了啥?找到main.c并打开,找到这一句:
`UART_HandleTypeDef huart1;` 声明一个串口结构体,用的一种面向对象的思想(别问我怎么知道是串口结构体不是其他的,不然地球不适合你),这里是个神马东东?带一下:


typedef struct
{
USART_TypeDef [i]Instance; /[/i]!< UART registers base address */

UART_InitTypeDef Init; /[i]!< UART communication parameters [/i]/

uint8_t [i]pTxBuffPtr; /[/i]!< Pointer to UART Tx transfer Buffer */

uint16_t TxXferSize; /[i]!< UART Tx Transfer size [/i]/

uint16_t TxXferCount; /[i]!< UART Tx Transfer Counter [/i]/

uint8_t [i]pRxBuffPtr; /[/i]!< Pointer to UART Rx transfer Buffer */

uint16_t RxXferSize; /[i]!< UART Rx Transfer size [/i]/

uint16_t RxXferCount; /[i]!< UART Rx Transfer Counter [/i]/

DMA_HandleTypeDef [i]hdmatx; /[/i]!< UART Tx DMA Handle parameters */

DMA_HandleTypeDef [i]hdmarx; /[/i]!< UART Rx DMA Handle parameters */

HAL_LockTypeDef Lock; /[i]!< Locking object [/i]/

__IO HAL_UART_StateTypeDef State; /[i]!< UART communication state [/i]/

__IO uint32_t ErrorCode; /[i]!< UART Error code [/i]/

}UART_HandleTypeDef;

这里强调一下,由于万恶的 “版圈法”,我的后续已不够全部写在这里,详见 《关于HAL库串口中断接收哪些路子 第二弹》,将就下吧!

解决串口通信的warning

回复

新手交流admin 回复了问题 • 2 人关注 • 1 个回复 • 45 次浏览 • 2019-10-14 17:26 • 来自相关话题

STM32F10x_RS485Modbus从站源程序

回复

经验分享现场总线/以太网/modbus开 发起了问题 • 1 人关注 • 0 个回复 • 83 次浏览 • 2019-10-05 11:11 • 来自相关话题

STM32 USART的RXNEIE不能置位或无法置位的原因(非QRE)

回复

问题困惑yuan123456 回复了问题 • 2 人关注 • 1 个回复 • 223 次浏览 • 2019-08-03 21:53 • 来自相关话题

记录stm32F4discovery板利用stm32cubemx实现串口的usart_IAP功能全过程

回复

软件教程chenlmm 回复了问题 • 26 人关注 • 21 个回复 • 10660 次浏览 • 2019-05-17 13:59 • 来自相关话题

请教使用cube 配置STM32F405RGT6 的串口 结果再输入脚PA10 USART_RX的模式选择中只有 PUSH POLL 没有INPUT

回复

问题困惑TeaCJ 回复了问题 • 1 人关注 • 2 个回复 • 294 次浏览 • 2019-04-05 11:26 • 来自相关话题

STM32L15系列IO模拟串口失败,请教

回复

问题困惑自带腹肌的西装 回复了问题 • 2 人关注 • 4 个回复 • 350 次浏览 • 2019-03-22 10:07 • 来自相关话题

分享一个串口的使用技巧(单字节中断后续字节处理)

回复

经验分享自带腹肌的西装 回复了问题 • 10 人关注 • 5 个回复 • 4335 次浏览 • 2019-03-19 09:28 • 来自相关话题

串口通讯莫名停止

回复

新手交流牙子男男 发起了问题 • 2 人关注 • 0 个回复 • 522 次浏览 • 2019-03-14 16:58 • 来自相关话题

关于按键和UART的问题 通过按键向串口输出不同的字符串,但是用串口软件没办法看到输出的信息

回复

问题困惑admin 回复了问题 • 2 人关注 • 1 个回复 • 674 次浏览 • 2018-12-03 21:12 • 来自相关话题

回调函数到底是如何调用的

回复

新手交流1533033440 回复了问题 • 3 人关注 • 2 个回复 • 2834 次浏览 • 2018-11-07 15:05 • 来自相关话题

关于stm32cube中UART串口的新库函数的一些东西理解,长久记录

回复

经验分享風影旋新月 回复了问题 • 28 人关注 • 10 个回复 • 32633 次浏览 • 2018-08-20 16:24 • 来自相关话题

分享一个由串口uart接收命令,来动态调整tim定时器pwm模式脉冲宽度的小实验

回复

软件教程想飞的四轴 回复了问题 • 43 人关注 • 19 个回复 • 12810 次浏览 • 2018-08-17 12:20 • 来自相关话题

stm32f407vet6 通过串口助手用错误波特率通信导致串口崩溃

回复

问题困惑admin 回复了问题 • 2 人关注 • 2 个回复 • 786 次浏览 • 2018-02-27 19:44 • 来自相关话题

STM32F103的HAL USART很奇怪的问题

回复

问题困惑「祭礼の蛇」 回复了问题 • 9 人关注 • 11 个回复 • 6771 次浏览 • 2017-12-01 10:26 • 来自相关话题

请教一个串口配置问题:

回复

问题困惑zhaobao511 发起了问题 • 1 人关注 • 0 个回复 • 733 次浏览 • 2017-08-18 11:32 • 来自相关话题

(转)关于stm32串口三种发送方式USART_IT_TXE/USART_IT_TC/DMA的理解

经验分享admin 发表了文章 • 4 个评论 • 8454 次浏览 • 2016-06-30 10:15 • 来自相关话题

第一种 USART_IT_TXE(发送寄存器空中断) 顾名思义,一旦寄存器空了 就会中断一次,为了防止一直进该中断或者不断往该寄存器装载数据,
在不装载数据时,一般需要做如下操作:
1.初始化的时候,屏蔽该中断
USART_ITConfig(USARTx, USART_IT_TXE, DISABLE);
2.要发送数据前,使能该中断
USART_ITConfig(USARTx, USART_IT_TXE, ENABLE);
3.发送数据结束后,屏蔽该中断
USART_ITConfig(USARTx, USART_IT_TXE, DISABLE);
第二种 USART_IT_TC(发送完成中断) 意为:发送寄存器发送完成之后,会进一次中断,它不像发送寄存器空中断,这时填入下一个数据,等到发送完成后再一次进入中断。这里需要注意的一点是,为了防止每次发生的第一个数据丢失,需要事先将该标志清零,USART_ClearFlag(USART2,USART_FLAG_TC)。
第三种方式采用DMA通道发送,具体的需要日后介绍。
另外不管是哪种发送方式,需要一提的是倘若用于485通信时,一定要检测USART_FLAG_TC,即进入一次发送完成标志,才可以切换接收模式,否则会造成最后一个字节未发出。
 
>>引用自:http://www.51hei.com/bbs/dpj-53169-1.html 查看全部
第一种 USART_IT_TXE(发送寄存器空中断) 顾名思义,一旦寄存器空了 就会中断一次,为了防止一直进该中断或者不断往该寄存器装载数据,
在不装载数据时,一般需要做如下操作:
1.初始化的时候,屏蔽该中断
USART_ITConfig(USARTx, USART_IT_TXE, DISABLE);
2.要发送数据前,使能该中断
USART_ITConfig(USARTx, USART_IT_TXE, ENABLE);
3.发送数据结束后,屏蔽该中断
USART_ITConfig(USARTx, USART_IT_TXE, DISABLE);
第二种 USART_IT_TC(发送完成中断) 意为:发送寄存器发送完成之后,会进一次中断,它不像发送寄存器空中断,这时填入下一个数据,等到发送完成后再一次进入中断。这里需要注意的一点是,为了防止每次发生的第一个数据丢失,需要事先将该标志清零,USART_ClearFlag(USART2,USART_FLAG_TC)。
第三种方式采用DMA通道发送,具体的需要日后介绍。
另外不管是哪种发送方式,需要一提的是倘若用于485通信时,一定要检测USART_FLAG_TC,即进入一次发送完成标志,才可以切换接收模式,否则会造成最后一个字节未发出。
 
>>引用自:http://www.51hei.com/bbs/dpj-53169-1.html

利用UART做调试利器

经验分享张腾威 发表了文章 • 7 个评论 • 2101 次浏览 • 2015-08-28 10:45 • 来自相关话题

简单几句语句,就能将Prinf函数使用啦,并将 文字数据 通过 串口 传到 电脑的串口调试助;
下面是步骤:
[]CUBE 中选择启用 UART,选择异步,设置好波特率,其他不用管,然后生产代码。[/][]加入下面语句[/]

#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /[i] __GNUC__ [/i]/

PUTCHAR_PROTOTYPE
{
/[i] Place your implementation of fputc here [/i]/
/[i] e.g. write a character to the USART [/i]/
USART_SendData(USART1, (uint8_t) ch);

/[i] Loop until the end of transmission [/i]/
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
{}
return ch;
}

3.在主函数中写入 printf("uart\r\n");然后打开串口助手,选择之前设置的波特率,看看效果吧 查看全部
简单几句语句,就能将Prinf函数使用啦,并将 文字数据 通过 串口 传到 电脑的串口调试助;
下面是步骤:
    []CUBE 中选择启用 UART,选择异步,设置好波特率,其他不用管,然后生产代码。[/][]加入下面语句[/]


#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /[i] __GNUC__ [/i]/

PUTCHAR_PROTOTYPE
{
/[i] Place your implementation of fputc here [/i]/
/[i] e.g. write a character to the USART [/i]/
USART_SendData(USART1, (uint8_t) ch);

/[i] Loop until the end of transmission [/i]/
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
{}
return ch;
}

3.在主函数中写入 printf("uart\r\n");然后打开串口助手,选择之前设置的波特率,看看效果吧

关于HAL库串口中断接收哪些路子 第一弹

经验分享L 发表了文章 • 11 个评论 • 5926 次浏览 • 2015-06-19 15:56 • 来自相关话题

一个串口中断搞了两周半,实在汗颜,群里也啰嗦了好多了,为了答谢给予我帮助的一些人,也为了回馈本论坛,就把这两个半周的领悟发出来,希望后来人不要再像我一样走弯路了!废话不多说,直接主题啦!
先说我的硬件平台,最常见的正点原子407开发板,一说“正点”又多想了哈!用过MX的请自动忽略第一弹,直瞅第二弹,节约你的时间。

1 .首先,打开MX,进入那一系列的配置,如图:









我的板载芯片是STM32F407ZGT6,这里自然也选407,LQFP封装,对应选择。









片子跑起来,除了电源的另一重要部分,时钟源,我的板子有外部晶振,虽然片子内部也有,但传说中外部的更精准,谁知道呢,反正我没试过,有就用呗,选外部晶振源。









串口的研究,这里不用多说,我用USART1调试,因为板子电路把USART1做成了RS232,并且都转换成了USB接口的,只要一根手机充电线就OK,总之就是简单,那就USART1吧,选择第一个异步通信。









这里要说下,调试接口,看到好多人都没选,也能跑得很happy,但是之前也试过仿真的时候遇到一些问题,还没总结原因到底是不是因为这个,但本人觉得人为定义调试方式总比片子自己判断来的靠谱吧,Maybe!我这里选得SWD调试方法。

到这里,管脚配置基本完了,进入下一步!(看到就这么个东东搞两周半,再汗颜一下)









这一步是配置时钟的,我觉得只要是这个论坛的,没有不知道的!(就是这么啃腚)之前说过要用外部晶振源,而我的外部晶振8M,这里自然要对应把其改成8M,之后就是一系列的锁相环倍频因子、锁相环倍频数之类的巴拉巴拉,串口挂在APB2上,一顿废话之后,我们要做的就是:
点选HSE外部高速,然后在点选PLLCLK倍频时钟,APB2框填那个最大的84M(额就爱最大滴),回车或任意空白单击左键,MX会帮我们搞定的。嘿嘿!










这一步是各个模块的相关配置,我们主要针对USART,NVIC里把串口的中断打勾,至于组优先和子优先就不研究了,默认0就OK!










至此,设置完毕,欢快的点那个齿轮,选择路径和开发平台,去生成代码吧,我的开发环境Keil5,就选这个了,重要提示,路径一定要是全英文字符,不然Keil要报错滴!

2 .这里,就开始说说串口了,我就喝口水,使劲罗嗦了,别嫌烦啊!
先说一个最基本的,神马是信息?(求别喷)记得信息论里大概这么个意思,有变化的的东西携带有信息,就好比我写个 1 ,它的信息量少的就是个 1,但我写个 n ,它的信息量基本就无穷大,因为我 n 是多少都可以 ,所以,我们计算机里传递信息就要搞个有复杂度,但又不能太复杂的东西,通俗点说:携带有穷信息的东东,于是,高低电平就出来了,于是,单个高低电平不满足需求,多信息位出来了,于是多信息位不好校验,接收,解析,串行协议就出来了。这么多于是,我不知道怎么解释,我也一知半解,但我觉得差不多到这里就可以了,现在说说串行协议里的几个关键词,波特率已经被老生长谈了,关于发送时间的换算也有了,我就一笔带过,我今天想说说数据位(因为它把我坑了):
常见的数据位就两种: 8位、9位,常用的数据位只有1种:8位,这里是学过微机原理人脑子里的概念,但是,实际情况是这样的8位机中: 一般是 0-8-0-0 结构,0起始位 8数据位 0奇偶校验位 0停止位=8位; 一种 1-8-0-1结构 ,1起始位 8数据位 0奇偶校验位 1停止位=10位。其他9位数据位的不研究,有兴趣的自己“吻度娘”,我们得到两个信息,
不同结构同一波特率数据量有差异;串行数据一帧,有且只会有一个8位的数据,也就是1Byte。


有以上结论,就去耍“码子”吧,打开项目,面对的是一系列系统初始化,包括串口滴(哇哈哈哈,ST真是贴心啊),看看他干了啥?找到main.c并打开,找到这一句:
`UART_HandleTypeDef huart1;` 声明一个串口结构体,用的一种面向对象的思想(别问我怎么知道是串口结构体不是其他的,不然地球不适合你),这里是个神马东东?带一下:


typedef struct
{
USART_TypeDef [i]Instance; /[/i]!< UART registers base address */

UART_InitTypeDef Init; /[i]!< UART communication parameters [/i]/

uint8_t [i]pTxBuffPtr; /[/i]!< Pointer to UART Tx transfer Buffer */

uint16_t TxXferSize; /[i]!< UART Tx Transfer size [/i]/

uint16_t TxXferCount; /[i]!< UART Tx Transfer Counter [/i]/

uint8_t [i]pRxBuffPtr; /[/i]!< Pointer to UART Rx transfer Buffer */

uint16_t RxXferSize; /[i]!< UART Rx Transfer size [/i]/

uint16_t RxXferCount; /[i]!< UART Rx Transfer Counter [/i]/

DMA_HandleTypeDef [i]hdmatx; /[/i]!< UART Tx DMA Handle parameters */

DMA_HandleTypeDef [i]hdmarx; /[/i]!< UART Rx DMA Handle parameters */

HAL_LockTypeDef Lock; /[i]!< Locking object [/i]/

__IO HAL_UART_StateTypeDef State; /[i]!< UART communication state [/i]/

__IO uint32_t ErrorCode; /[i]!< UART Error code [/i]/

}UART_HandleTypeDef;

这里强调一下,由于万恶的 “版圈法”,我的后续已不够全部写在这里,详见 《关于HAL库串口中断接收哪些路子 第二弹》,将就下吧! 查看全部
一个串口中断搞了两周半,实在汗颜,群里也啰嗦了好多了,为了答谢给予我帮助的一些人,也为了回馈本论坛,就把这两个半周的领悟发出来,希望后来人不要再像我一样走弯路了!废话不多说,直接主题啦!
先说我的硬件平台,最常见的正点原子407开发板,一说“正点”又多想了哈!用过MX的请自动忽略第一弹,直瞅第二弹,节约你的时间。

1 .首先,打开MX,进入那一系列的配置,如图:



1.png



我的板载芯片是STM32F407ZGT6,这里自然也选407,LQFP封装,对应选择。



2.png



片子跑起来,除了电源的另一重要部分,时钟源,我的板子有外部晶振,虽然片子内部也有,但传说中外部的更精准,谁知道呢,反正我没试过,有就用呗,选外部晶振源。



3.png



串口的研究,这里不用多说,我用USART1调试,因为板子电路把USART1做成了RS232,并且都转换成了USB接口的,只要一根手机充电线就OK,总之就是简单,那就USART1吧,选择第一个异步通信。



4.png



这里要说下,调试接口,看到好多人都没选,也能跑得很happy,但是之前也试过仿真的时候遇到一些问题,还没总结原因到底是不是因为这个,但本人觉得人为定义调试方式总比片子自己判断来的靠谱吧,Maybe!我这里选得SWD调试方法。

到这里,管脚配置基本完了,进入下一步!(看到就这么个东东搞两周半,再汗颜一下)



5.png



这一步是配置时钟的,我觉得只要是这个论坛的,没有不知道的!(就是这么啃腚)之前说过要用外部晶振源,而我的外部晶振8M,这里自然要对应把其改成8M,之后就是一系列的锁相环倍频因子、锁相环倍频数之类的巴拉巴拉,串口挂在APB2上,一顿废话之后,我们要做的就是:
点选HSE外部高速,然后在点选PLLCLK倍频时钟,APB2框填那个最大的84M(额就爱最大滴),回车或任意空白单击左键,MX会帮我们搞定的。嘿嘿!



6.png




这一步是各个模块的相关配置,我们主要针对USART,NVIC里把串口的中断打勾,至于组优先和子优先就不研究了,默认0就OK!



7.png




至此,设置完毕,欢快的点那个齿轮,选择路径和开发平台,去生成代码吧,我的开发环境Keil5,就选这个了,重要提示,路径一定要是全英文字符,不然Keil要报错滴!

2 .这里,就开始说说串口了,我就喝口水,使劲罗嗦了,别嫌烦啊!
先说一个最基本的,神马是信息?(求别喷)记得信息论里大概这么个意思,有变化的的东西携带有信息,就好比我写个 1 ,它的信息量少的就是个 1,但我写个 n ,它的信息量基本就无穷大,因为我 n 是多少都可以 ,所以,我们计算机里传递信息就要搞个有复杂度,但又不能太复杂的东西,通俗点说:携带有穷信息的东东,于是,高低电平就出来了,于是,单个高低电平不满足需求,多信息位出来了,于是多信息位不好校验,接收,解析,串行协议就出来了。这么多于是,我不知道怎么解释,我也一知半解,但我觉得差不多到这里就可以了,现在说说串行协议里的几个关键词,波特率已经被老生长谈了,关于发送时间的换算也有了,我就一笔带过,我今天想说说数据位(因为它把我坑了):
常见的数据位就两种: 8位、9位,常用的数据位只有1种:8位,这里是学过微机原理人脑子里的概念,但是,实际情况是这样的8位机中: 一般是 0-8-0-0 结构,0起始位 8数据位 0奇偶校验位 0停止位=8位; 一种 1-8-0-1结构 ,1起始位 8数据位 0奇偶校验位 1停止位=10位。其他9位数据位的不研究,有兴趣的自己“吻度娘”,我们得到两个信息,
不同结构同一波特率数据量有差异;串行数据一帧,有且只会有一个8位的数据,也就是1Byte。


有以上结论,就去耍“码子”吧,打开项目,面对的是一系列系统初始化,包括串口滴(哇哈哈哈,ST真是贴心啊),看看他干了啥?找到main.c并打开,找到这一句:
`UART_HandleTypeDef huart1;` 声明一个串口结构体,用的一种面向对象的思想(别问我怎么知道是串口结构体不是其他的,不然地球不适合你),这里是个神马东东?带一下:


typedef struct
{
USART_TypeDef [i]Instance; /[/i]!< UART registers base address */

UART_InitTypeDef Init; /[i]!< UART communication parameters [/i]/

uint8_t [i]pTxBuffPtr; /[/i]!< Pointer to UART Tx transfer Buffer */

uint16_t TxXferSize; /[i]!< UART Tx Transfer size [/i]/

uint16_t TxXferCount; /[i]!< UART Tx Transfer Counter [/i]/

uint8_t [i]pRxBuffPtr; /[/i]!< Pointer to UART Rx transfer Buffer */

uint16_t RxXferSize; /[i]!< UART Rx Transfer size [/i]/

uint16_t RxXferCount; /[i]!< UART Rx Transfer Counter [/i]/

DMA_HandleTypeDef [i]hdmatx; /[/i]!< UART Tx DMA Handle parameters */

DMA_HandleTypeDef [i]hdmarx; /[/i]!< UART Rx DMA Handle parameters */

HAL_LockTypeDef Lock; /[i]!< Locking object [/i]/

__IO HAL_UART_StateTypeDef State; /[i]!< UART communication state [/i]/

__IO uint32_t ErrorCode; /[i]!< UART Error code [/i]/

}UART_HandleTypeDef;

这里强调一下,由于万恶的 “版圈法”,我的后续已不够全部写在这里,详见 《关于HAL库串口中断接收哪些路子 第二弹》,将就下吧!

USART的另类应用协议:DMX512协议

经验分享admin 发表了文章 • 2 个评论 • 3409 次浏览 • 2015-01-20 21:19 • 来自相关话题

DMX512 协议是美国剧场技术协会( United States Institute for Theater Technology, USITT) 制定的数字多路复用协议, 其制定的初衷是为了使舞台、剧场等地所使用的众多的调光器和控制器能相互兼容。虽然它不是一个行业或国家标准, 但是由于它的简单性和实用性, 自从出台以来, 得到了世界各地生产商和使用者普遍承认,这个协议在LED控制方面应用很广泛,利用STM32 USART可以高速传输的特性,我们很容易用STM32来实现DMX512协议。
(1)数据的格式及传输
DMX512 协议规定数据以数据包的形式通过异步通讯的方式进行传输。每个数据包由若干数据帧组成, 每帧数据包括1 位低电平起始位、8 位数据位和2 位高电平停止位。DMX 协议要求数据传输的波特率为250kb/s, 亦即每位的传输时间为4us, 每帧数据的传输时间为44us, 它支持多达512 帧数据传输, 每帧数据与相应的控制支路相对应。数据包的传送要符合一定的格式和时序要求。为了使接收器能够分辨出第一帧数据, 每一个数据包以一个不短于88us 的低电平信号为起始信号, 即所谓的“Break”信号, 接收器接收到“Break”信号就准备接受随后而来的数据帧; 紧接着“Break”信号之后是不短于8us 的高电平信号M. a. b ( Mark after Break) ; 之后就是数据帧。在DMX512 协议中, M. a. b 之后的第一帧数据被称
为“Star-t code”, 在协议中规定其为零, 但在实际应用中可以由生产厂家自己确定其具体的值, 以传递特殊消息。“Star-t code”标明其后面的数据是8 位控制信号数据帧。数据帧之间可以有时间间隔, 也可以没有; 同样, 数据包之间可以有时间间隔, 也可以没有。DMX512 协议规定“Break”信号、M. a. b 信号的最短时间, 并规定“Break”信号、M. a. b 信号、
数据帧之间及数据包之间的时间间隔的最大值不得超过1s, 否则做出错处理, 但是DMX512 协议并未对出错处理做任何规定。为了严格实现DMX512 数据的时序要求,“Break”和M. a. b信号我们可以用定时器来实现。
具体的UART配置如下:
USART_InitStructure.USART_BaudRate = 250000;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_2;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &amp;USART_InitStructure);
发送DMX512信号过程如下,先把UART的TX脚配置为普通的GPIO并输出低电平,然后启动定时器计时88us, 时器到后把TX脚置为高电平并计时8us, 时器到了后在配为UART模式用DMA方式把数据发出。
DMX512信号的接收是个难点,一般直接配为UART接收就行,不需要在UART模式和GPIO模式间切换,但需要在接收过程中检查接收到“Break”信号时的状态是有帧错误出现,并且接收数据全为零,这样的话可以确认已经收到“Break”信号,随后数据正常DMA接收就行了。
下面这个是做出来的效果。。
有兴趣的可以百度搜下资料 查看全部
DMX512 协议是美国剧场技术协会( United States Institute for Theater Technology, USITT) 制定的数字多路复用协议, 其制定的初衷是为了使舞台、剧场等地所使用的众多的调光器和控制器能相互兼容。虽然它不是一个行业或国家标准, 但是由于它的简单性和实用性, 自从出台以来, 得到了世界各地生产商和使用者普遍承认,这个协议在LED控制方面应用很广泛,利用STM32 USART可以高速传输的特性,我们很容易用STM32来实现DMX512协议。
(1)数据的格式及传输
DMX512 协议规定数据以数据包的形式通过异步通讯的方式进行传输。每个数据包由若干数据帧组成, 每帧数据包括1 位低电平起始位、8 位数据位和2 位高电平停止位。DMX 协议要求数据传输的波特率为250kb/s, 亦即每位的传输时间为4us, 每帧数据的传输时间为44us, 它支持多达512 帧数据传输, 每帧数据与相应的控制支路相对应。数据包的传送要符合一定的格式和时序要求。为了使接收器能够分辨出第一帧数据, 每一个数据包以一个不短于88us 的低电平信号为起始信号, 即所谓的“Break”信号, 接收器接收到“Break”信号就准备接受随后而来的数据帧; 紧接着“Break”信号之后是不短于8us 的高电平信号M. a. b ( Mark after Break) ; 之后就是数据帧。在DMX512 协议中, M. a. b 之后的第一帧数据被称
为“Star-t code”, 在协议中规定其为零, 但在实际应用中可以由生产厂家自己确定其具体的值, 以传递特殊消息。“Star-t code”标明其后面的数据是8 位控制信号数据帧。数据帧之间可以有时间间隔, 也可以没有; 同样, 数据包之间可以有时间间隔, 也可以没有。DMX512 协议规定“Break”信号、M. a. b 信号的最短时间, 并规定“Break”信号、M. a. b 信号、
数据帧之间及数据包之间的时间间隔的最大值不得超过1s, 否则做出错处理, 但是DMX512 协议并未对出错处理做任何规定。为了严格实现DMX512 数据的时序要求,“Break”和M. a. b信号我们可以用定时器来实现。
具体的UART配置如下:
USART_InitStructure.USART_BaudRate = 250000;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_2;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &amp;USART_InitStructure);
发送DMX512信号过程如下,先把UART的TX脚配置为普通的GPIO并输出低电平,然后启动定时器计时88us, 时器到后把TX脚置为高电平并计时8us, 时器到了后在配为UART模式用DMA方式把数据发出。
DMX512信号的接收是个难点,一般直接配为UART接收就行,不需要在UART模式和GPIO模式间切换,但需要在接收过程中检查接收到“Break”信号时的状态是有帧错误出现,并且接收数据全为零,这样的话可以确认已经收到“Break”信号,随后数据正常DMA接收就行了。
下面这个是做出来的效果。。
有兴趣的可以百度搜下资料

(转)STM32串口驱动(拼音检索测试通过)(环形队列+内存动态分配+DMA,写的不错,借鉴下

其他分享popdes 发表了文章 • 1 个评论 • 2160 次浏览 • 2015-01-18 20:30 • 来自相关话题

下面摘录一段:
在设计串口驱动的过程中,要遵循的两条准则是:
1 :尽量的减少程序运行的时间。
2 :尽量的减少程序所占用的内存。
譬如,下面的一段程序:
程序段 1-1


/[i] 指针是指向 ptr ,需要发送 count个数据[/i]/
void USART1WriteDataToBuffer( * ptr , u8 count )
{
/[i] 判断数据是否发送完毕 [/i]/
while ( count-- )
{
/[i] 发送数据 [/i]/
USART1SendByte ( *ptr+);
/[i] 等待这个数据发送完毕,然后进入下一个数据的发送过程[/i]/
while(USART_GetFlagStatus(USART1,USART_FLAG_TC);
}
/[i] 数据发送完毕,返回 [/i]/
}

很明显 , 这段程序在实际应用中将会产生灾难性的后果,首先,当发送数据送到寄存器
启动发送以后 , CPU 就一直在等待这个数据发送完成,然后进入下一步数据的发送,这样,
直到所有要发送的数据完成, CPU 才能做其他的事情,相对于CPU内核运行的速度而言,
串口外设的运行速度是非常快的 , 让一个速度非常快的设备去等待相对运行很慢的设备,程序的
效率是非常低下的。
所以必须采用中断的方式发送数据。

算了打字累,具体的自己去【资源下载】本站网盘里下载看吧。 查看全部
下面摘录一段:
在设计串口驱动的过程中,要遵循的两条准则是:
1 :尽量的减少程序运行的时间。
2 :尽量的减少程序所占用的内存。
譬如,下面的一段程序:
程序段 1-1


/[i] 指针是指向 ptr ,需要发送 count个数据[/i]/
void USART1WriteDataToBuffer( * ptr , u8 count )
{
/[i] 判断数据是否发送完毕 [/i]/
while ( count-- )
{
/[i] 发送数据 [/i]/
USART1SendByte ( *ptr+);
/[i] 等待这个数据发送完毕,然后进入下一个数据的发送过程[/i]/
while(USART_GetFlagStatus(USART1,USART_FLAG_TC);
}
/[i] 数据发送完毕,返回 [/i]/
}

很明显 , 这段程序在实际应用中将会产生灾难性的后果,首先,当发送数据送到寄存器
启动发送以后 , CPU 就一直在等待这个数据发送完成,然后进入下一步数据的发送,这样,
直到所有要发送的数据完成, CPU 才能做其他的事情,相对于CPU内核运行的速度而言,
串口外设的运行速度是非常快的 , 让一个速度非常快的设备去等待相对运行很慢的设备,程序的
效率是非常低下的。
所以必须采用中断的方式发送数据。

算了打字累,具体的自己去【资源下载】本站网盘里下载看吧。

(转载)关于UART中用Printf()输出float型数据

经验分享admin 发表了文章 • 2 个评论 • 2172 次浏览 • 2014-12-23 13:05 • 来自相关话题

在coocox上看到有人问关于Printf打印浮点型数据会输出0或者其他的问题
The code:
printf("float: %f \n\r", 10.02);
Produce that result:
float: H
帖子的楼猪问必须使用printf下怎么输出浮点型数据呢?
斑猪做了回答,代码如下:
The retarget printf don't support print float value now.
目前不支持float型......
然后可以做一些修改使其支持,如下
To printf float argument through UART, Semihosting or other communication method, you cannot use the Retarget Printf component in CoIDE. That component is a simple example for print int, char value.

You can do the followings:

[]Check C Library Component[/]
[]Open syscall/syscall.c, then modify the[/]

int _read(int file, char ptr, int len)
{
return 0;
}
int _write(int file, char ptr, int len)
{
return len;
}

to:
int _read(int file, char ptr, int len) {
int c, rxCount = 0;

(void) file;

while (len--) {
if ((c = GetChar()) != -1) { // Getchar Function need to be replaced by the function you used to get values.
ptr++ = c;
rxCount++;
} else {
break;
}
}

if (rxCount <= 0) {
return -1; / Error exit /
}

return rxCount;
}

int _write(int file, char ptr, int len) {
int txCount;

(void) file;

for (txCount = 0; txCount < len; txCount++) {
SendChar(ptr++); // SendChar Function need to be replaced by the function you used to print values.

}

return len;
}

[]Then you can use printf, scanf or other c library function to print and get value in your project.[/]然后斑猪又提到一点:
The old version often hung up on Win7.

The new version support SWO Trace, and quicker, more stable than the old version.

Different version of firmware need different version of driver.

The virture COM is for SWO trace for M3 chips only (which have ITM function). They cannot be use as UART to USB function.
貌似意思是用usb虚拟串口的话,这样的printf是不能这样用的...................
本文转自coocox论坛,如有冒犯请指出,谢谢 查看全部
在coocox上看到有人问关于Printf打印浮点型数据会输出0或者其他的问题
The code:
printf("float: %f \n\r", 10.02);
Produce that result:
float: H
帖子的楼猪问必须使用printf下怎么输出浮点型数据呢?
斑猪做了回答,代码如下:
The retarget printf don't support print float value now.
目前不支持float型......
然后可以做一些修改使其支持,如下
To printf float argument through UART, Semihosting or other communication method, you cannot use the Retarget Printf component in CoIDE. That component is a simple example for print int, char value.

You can do the followings:

    []Check C Library Component[/]

    []Open syscall/syscall.c, then modify the[/]


int _read(int file, char ptr, int len)
{
return 0;
}
int _write(int file, char ptr, int len)
{
return len;
}

to:
int _read(int file, char ptr, int len) {
int c, rxCount = 0;

(void) file;

while (len--) {
if ((c = GetChar()) != -1) { // Getchar Function need to be replaced by the function you used to get values.
ptr++ = c;
rxCount++;
} else {
break;
}
}

if (rxCount <= 0) {
return -1; / Error exit /
}

return rxCount;
}

int _write(int file, char ptr, int len) {
int txCount;

(void) file;

for (txCount = 0; txCount < len; txCount++) {
SendChar(ptr++); // SendChar Function need to be replaced by the function you used to print values.

}

return len;
}

    []Then you can use printf, scanf or other c library function to print and get value in your project.[/]
然后斑猪又提到一点:
The old version often hung up on Win7.

The new version support SWO Trace, and quicker, more stable than the old version.

Different version of firmware need different version of driver.

The virture COM is for SWO trace for M3 chips only (which have ITM function). They cannot be use as UART to USB function.
貌似意思是用usb虚拟串口的话,这样的printf是不能这样用的...................
本文转自coocox论坛,如有冒犯请指出,谢谢

usart的真正用法之一堆栈,push和pop处理uart得到的数据,不要再说stm32cube的新库函数不好用了

软件教程admin 发表了文章 • 17 个评论 • 7205 次浏览 • 2014-10-22 14:17 • 来自相关话题

b[/b]

如题:
刚开始用stm32cube的最新uart库函数的时候其实我也发牢骚了半天.
甚至不知道应该怎么去处理数据..........
汗,只怪自己就没怎么认真学过,还敢自称会用uart,汗颜
以前就是直接接收到数据,然后判断处理,这个其实就是小成用法.
下面列出研究了两天的稍微大成点的用法
将uart取得的数据,经过入栈存入到一个数据表中,然后用pop出栈进行数据处理
大体做法是:
要进行传输的数据必须格式化,例如设置数据头和数据尾来判断一帧完整的数据.
数据的头和尾之间是有效数据,可以包含数据的定义和数据本身
单片机接受到数据后,先存入到
HAL_UART_Receive_IT(&huart1, que._data, QUEUE_max_size);
这句话的que._data数据表中,这个数据表可以设置的长一点,不会溢出就行
然后写一个程序处理这个里面的数据,第一步就是查找判断这个数据是不是按照上面的数据格式
的数据,如果不是则舍弃,否则,按照你的数据规则取得这个有效的数据例如queue_find_cmd(cmd_buffer,30),其中cmd_buffer里面就是得到的数据.
然后可以依照规则将每位进行分解处理,例如cmd_buffer[1]=0x00表示这次传输的是数字,=0x01则表示传输的是字符串,然后cmd_buffer[2]+(cmd_buffer[3]<<8)+(cmd_buffer[4]<<16)+(cmd_buffer[5]<<24).
这样表示后面的是连续32位数据,呵呵
2楼继续. 查看全部
b[/b]

如题:
刚开始用stm32cube的最新uart库函数的时候其实我也发牢骚了半天.
甚至不知道应该怎么去处理数据..........
汗,只怪自己就没怎么认真学过,还敢自称会用uart,汗颜
以前就是直接接收到数据,然后判断处理,这个其实就是小成用法.
下面列出研究了两天的稍微大成点的用法
将uart取得的数据,经过入栈存入到一个数据表中,然后用pop出栈进行数据处理
大体做法是:
要进行传输的数据必须格式化,例如设置数据头和数据尾来判断一帧完整的数据.
数据的头和尾之间是有效数据,可以包含数据的定义和数据本身
单片机接受到数据后,先存入到
HAL_UART_Receive_IT(&huart1, que._data, QUEUE_max_size);
这句话的que._data数据表中,这个数据表可以设置的长一点,不会溢出就行
然后写一个程序处理这个里面的数据,第一步就是查找判断这个数据是不是按照上面的数据格式
的数据,如果不是则舍弃,否则,按照你的数据规则取得这个有效的数据例如queue_find_cmd(cmd_buffer,30),其中cmd_buffer里面就是得到的数据.
然后可以依照规则将每位进行分解处理,例如cmd_buffer[1]=0x00表示这次传输的是数字,=0x01则表示传输的是字符串,然后cmd_buffer[2]+(cmd_buffer[3]<<8)+(cmd_buffer[4]<<16)+(cmd_buffer[5]<<24).
这样表示后面的是连续32位数据,呵呵
2楼继续.

关于HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)的研究

问题困惑admin 发表了文章 • 10 个评论 • 9443 次浏览 • 2014-10-14 00:19 • 来自相关话题

HAL_UART_Receive_IT(UART_HandleTypeDef huart, uint8_t pData, uint16_t Size)
从它的函数内容考看,其实就是初始化了下uart端口,定义了下接收到的数据的缓存器名,还有定义了接收尺寸,然后开启了UART_IT_RXNE,即接收非空中断,然后静等中断发生。
2楼继续。

中断发生后。
进入
void USART1_IRQHandler(void)
{
HAL_NVIC_ClearPendingIRQ(USART1_IRQn);
HAL_UART_IRQHandler(&huart1);
// cont_uart++;
}
先清除等待标志,后进入中断处理
进入
tmp1 = __HAL_UART_GET_FLAG(huart, UART_FLAG_RXNE);
tmp2 = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_RXNE);
/ UART in mode Receiver ---------------------------------------------------/
if((tmp1 != RESET) && (tmp2 != RESET))
{
UART_Receive_IT(huart);
}
判断接收到非空数据,并且RXEN中断开启了,则执行数据接收UART_Receive_IT(huart);
8位,none,所以执行
if(huart->Init.Parity == UART_PARITY_NONE)
{
*huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);
}
得到数据,存到pRxBuffPtr的指向地址缓存器里
3楼继续

接上面
if(--huart->RxXferCount == 0)
{
__HAL_UART_DISABLE_IT(huart, UART_IT_RXNE);

/ Check if a transmit process is ongoing or not /
if(huart->State == HAL_UART_STATE_BUSY_TX_RX)
{
huart->State = HAL_UART_STATE_BUSY_TX;
}
else
{
/ Disable the UART Parity Error Interrupt /
__HAL_UART_DISABLE_IT(huart, UART_IT_PE);

/ Disable the UART Error Interrupt: (Frame error, noise error, overrun error) /
__HAL_UART_DISABLE_IT(huart, UART_IT_ERR);

huart->State = HAL_UART_STATE_READY;
}
HAL_UART_RxCpltCallback(huart);

return HAL_OK;
}
计数自减1,判断是否是0,不是0则说明还么接收完
则程序返回,再次接收到一个字节,产生中断再次执行。
直到--huart->RxXferCount == 0
__HAL_UART_DISABLE_IT(huart, UART_IT_RXNE); 关闭RXEN接收非空中断
再判断是否在传送,没有则关闭UART Parity Error Interrupt
关闭UART Error Interrupt: (Frame error, noise error, overrun error)
并且 调用接收完成回调函数,HAL_UART_RxCpltCallback(huart);
继续接4楼

接楼上
说明每次接收完数据,只要没发送状态
uart的接收中断全部关闭了,要想连续的接收数据,则需要在
HAL_UART_RxCpltCallback(huart);函数中开启RXEN中断

/ Enable the UART Parity Error Interrupt /
__HAL_UART_ENABLE_IT(huart, UART_IT_PE);

/ Enable the UART Error Interrupt: (Frame error, noise error, overrun error) /
__HAL_UART_ENABLE_IT(huart, UART_IT_ERR);

/ Process Unlocked /
__HAL_UNLOCK(huart);

/ Enable the UART Data Register not empty Interrupt /
__HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);

即需要再次调用HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 8);函数,。
下面测试:
在main中添加
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
/* NOTE: This function Should not be modified, when the callback is needed,
the HAL_UART_TxCpltCallback could be implemented in the user file
*/
HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 8);

}
测试失败,第一次能接收到,第二次数据接收不到。
将 HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 8);写入到
void USART1_IRQHandler(void)
{
HAL_NVIC_ClearPendingIRQ(USART1_IRQn);
HAL_UART_IRQHandler(&huart1);
HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 8);
cont_uart++;
}
测试成功,可以接收到8位数据。
不过,如果数据超过8位,则超过部分会覆盖掉以前的数据
如:8位数据是,1、2、3、4、5、6、7、8
发送的10位数据:则接收到的会把前两位覆盖,最终接收的数据是
10、9、3、4、5、6、7、8
测试代码是接收8位,要改成10位同样道理,反正超过了接收的就是不对的数据

分析上面的
void USART1_IRQHandler(void)
{
HAL_NVIC_ClearPendingIRQ(USART1_IRQn);
HAL_UART_IRQHandler(&huart1);
HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 8);
cont_uart++;
}
接收到小于设定的长度值无所谓,能正常获取
大于之后覆盖
因为接收完8个数据,清除中断,然后Hal_ready = ok,等到第九个数据过来产生中断 查看全部
HAL_UART_Receive_IT(UART_HandleTypeDef huart, uint8_t pData, uint16_t Size)
从它的函数内容考看,其实就是初始化了下uart端口,定义了下接收到的数据的缓存器名,还有定义了接收尺寸,然后开启了UART_IT_RXNE,即接收非空中断,然后静等中断发生。
2楼继续。

中断发生后。
进入
void USART1_IRQHandler(void)
{
HAL_NVIC_ClearPendingIRQ(USART1_IRQn);
HAL_UART_IRQHandler(&huart1);
// cont_uart++;
}
先清除等待标志,后进入中断处理
进入
tmp1 = __HAL_UART_GET_FLAG(huart, UART_FLAG_RXNE);
tmp2 = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_RXNE);
/ UART in mode Receiver ---------------------------------------------------/
if((tmp1 != RESET) && (tmp2 != RESET))
{
UART_Receive_IT(huart);
}
判断接收到非空数据,并且RXEN中断开启了,则执行数据接收UART_Receive_IT(huart);
8位,none,所以执行
if(huart->Init.Parity == UART_PARITY_NONE)
{
*huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);
}
得到数据,存到pRxBuffPtr的指向地址缓存器里
3楼继续

接上面
if(--huart->RxXferCount == 0)
{
__HAL_UART_DISABLE_IT(huart, UART_IT_RXNE);

/ Check if a transmit process is ongoing or not /
if(huart->State == HAL_UART_STATE_BUSY_TX_RX)
{
huart->State = HAL_UART_STATE_BUSY_TX;
}
else
{
/ Disable the UART Parity Error Interrupt /
__HAL_UART_DISABLE_IT(huart, UART_IT_PE);

/ Disable the UART Error Interrupt: (Frame error, noise error, overrun error) /
__HAL_UART_DISABLE_IT(huart, UART_IT_ERR);

huart->State = HAL_UART_STATE_READY;
}
HAL_UART_RxCpltCallback(huart);

return HAL_OK;
}
计数自减1,判断是否是0,不是0则说明还么接收完
则程序返回,再次接收到一个字节,产生中断再次执行。
直到--huart->RxXferCount == 0
__HAL_UART_DISABLE_IT(huart, UART_IT_RXNE); 关闭RXEN接收非空中断
再判断是否在传送,没有则关闭UART Parity Error Interrupt
关闭UART Error Interrupt: (Frame error, noise error, overrun error)
并且 调用接收完成回调函数,HAL_UART_RxCpltCallback(huart);
继续接4楼

接楼上
说明每次接收完数据,只要没发送状态
uart的接收中断全部关闭了,要想连续的接收数据,则需要在
HAL_UART_RxCpltCallback(huart);函数中开启RXEN中断

/ Enable the UART Parity Error Interrupt /
__HAL_UART_ENABLE_IT(huart, UART_IT_PE);

/ Enable the UART Error Interrupt: (Frame error, noise error, overrun error) /
__HAL_UART_ENABLE_IT(huart, UART_IT_ERR);

/ Process Unlocked /
__HAL_UNLOCK(huart);

/ Enable the UART Data Register not empty Interrupt /
__HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);

即需要再次调用HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 8);函数,。
下面测试:
在main中添加
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
/* NOTE: This function Should not be modified, when the callback is needed,
the HAL_UART_TxCpltCallback could be implemented in the user file
*/
HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 8);

}
测试失败,第一次能接收到,第二次数据接收不到。
将 HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 8);写入到
void USART1_IRQHandler(void)
{
HAL_NVIC_ClearPendingIRQ(USART1_IRQn);
HAL_UART_IRQHandler(&huart1);
HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 8);
cont_uart++;
}
测试成功,可以接收到8位数据。
不过,如果数据超过8位,则超过部分会覆盖掉以前的数据
如:8位数据是,1、2、3、4、5、6、7、8
发送的10位数据:则接收到的会把前两位覆盖,最终接收的数据是
10、9、3、4、5、6、7、8
测试代码是接收8位,要改成10位同样道理,反正超过了接收的就是不对的数据

分析上面的
void USART1_IRQHandler(void)
{
HAL_NVIC_ClearPendingIRQ(USART1_IRQn);
HAL_UART_IRQHandler(&huart1);
HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 8);
cont_uart++;
}
接收到小于设定的长度值无所谓,能正常获取
大于之后覆盖
因为接收完8个数据,清除中断,然后Hal_ready = ok,等到第九个数据过来产生中断