UART

UART

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

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

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

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

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

软件教程overture1928 回复了问题 • 21 人关注 • 19 个回复 • 7490 次浏览 • 2018-11-10 21:37 • 来自相关话题

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

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

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

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

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

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

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

经验分享skyhahaha 回复了问题 • 9 人关注 • 4 个回复 • 3312 次浏览 • 2018-02-08 11:44 • 来自相关话题

STM32F103的HAL USART很奇怪的问题

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

请教一个串口配置问题:

回复

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

(已弃)利用串口来模拟spi发送一定数量的上升沿脉冲

回复

其他分享admin 回复了问题 • 1 人关注 • 1 个回复 • 916 次浏览 • 2017-08-02 13:05 • 来自相关话题

在低波特率下使用RS-485总线的一个小技巧

经验分享jialian4213 回复了问题 • 2 人关注 • 2 个回复 • 1611 次浏览 • 2017-07-14 18:48 • 来自相关话题

一直不理解DMA不需要耗系统时间的原因,今天做了个实验才终于理解了,O(∩_∩)O哈!

经验分享xiaohuihui 回复了问题 • 10 人关注 • 3 个回复 • 3585 次浏览 • 2016-12-17 15:22 • 来自相关话题

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

经验分享admin 发表了文章 • 4 个评论 • 6191 次浏览 • 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

(转)串口可以配置成用DMA的方式接收数据,不过DMA需要定长才能产生接收中断,如何接收可变长度的数据呢?

经验分享~*静ヅ清晰._ 回复了问题 • 5 人关注 • 3 个回复 • 3418 次浏览 • 2016-05-23 13:10 • 来自相关话题

利用UART做调试利器

经验分享张腾威 发表了文章 • 5 个评论 • 1732 次浏览 • 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 个评论 • 4934 次浏览 • 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库串口中断接收哪些路子 第二弹》,将就下吧!

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

回复

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

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

回复

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

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

回复

软件教程overture1928 回复了问题 • 21 人关注 • 19 个回复 • 7490 次浏览 • 2018-11-10 21:37 • 来自相关话题

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

回复

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

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

回复

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

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

回复

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

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

回复

经验分享skyhahaha 回复了问题 • 9 人关注 • 4 个回复 • 3312 次浏览 • 2018-02-08 11:44 • 来自相关话题

STM32F103的HAL USART很奇怪的问题

回复

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

请教一个串口配置问题:

回复

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

(已弃)利用串口来模拟spi发送一定数量的上升沿脉冲

回复

其他分享admin 回复了问题 • 1 人关注 • 1 个回复 • 916 次浏览 • 2017-08-02 13:05 • 来自相关话题

在低波特率下使用RS-485总线的一个小技巧

回复

经验分享jialian4213 回复了问题 • 2 人关注 • 2 个回复 • 1611 次浏览 • 2017-07-14 18:48 • 来自相关话题

一直不理解DMA不需要耗系统时间的原因,今天做了个实验才终于理解了,O(∩_∩)O哈!

回复

经验分享xiaohuihui 回复了问题 • 10 人关注 • 3 个回复 • 3585 次浏览 • 2016-12-17 15:22 • 来自相关话题

(转)串口可以配置成用DMA的方式接收数据,不过DMA需要定长才能产生接收中断,如何接收可变长度的数据呢?

回复

经验分享~*静ヅ清晰._ 回复了问题 • 5 人关注 • 3 个回复 • 3418 次浏览 • 2016-05-23 13:10 • 来自相关话题

(转)分析和理解stm32的IAP功能怎么实现的?

回复

经验分享admin 发起了问题 • 4 人关注 • 0 个回复 • 2415 次浏览 • 2015-07-28 17:06 • 来自相关话题

cube生成的串口方面的代码,用串口收数据时怎么个过程?特别是其中的RxXferCount等变量如何变化

回复

问题困惑三好学生 回复了问题 • 2 人关注 • 3 个回复 • 3033 次浏览 • 2015-04-03 11:25 • 来自相关话题

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

经验分享admin 发表了文章 • 4 个评论 • 6191 次浏览 • 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做调试利器

经验分享张腾威 发表了文章 • 5 个评论 • 1732 次浏览 • 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 个评论 • 4934 次浏览 • 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 发表了文章 • 1 个评论 • 2369 次浏览 • 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 个评论 • 1731 次浏览 • 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 个评论 • 1858 次浏览 • 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 个评论 • 6445 次浏览 • 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 个评论 • 7203 次浏览 • 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,等到第九个数据过来产生中断

stm32cube中文教程:AD用TIM8定时采集,uart3输出

软件教程admin 发表了文章 • 15 个评论 • 3973 次浏览 • 2014-10-13 23:45 • 来自相关话题

stm32cube中文教程:AD用TIM8定时采集,uart3输出
arm片子stm32f407ZGT,用ADC1,TIM8,UART3,。
ad脚PB0,uart脚PB10和11,PF6输出led灯。
晶振25M,时钟168M。
stm32cubemx软件设置:
uart9600,8,0,1,不使能uart中断,TX:PULL_up,fast。RX:NO PULL_UP,fast
DMA不使能。
ADC设置:修改了continuous conversion mode:enable;end of conversion selection :Eoc flag signle channel

External Trigger conversion Edge : Trigger detection on the rising edge
External Trigger Conversion Source : Time 8 Trigger Out event
其余的默认即可。
ADC中断不使能。
TIme8定时设置:
Prescaler(psc - 16 bits value) : 0
counter mode : UP
counter Period(autoreload register - 16 bits value) : 60
internal clock division (CDK) : NO Division
Repetition counter(RCR - 8bits value) : 0
slave mode controller : trigger mode
master/slave mode : Disable
trigger event selection : Update enent
不使能任何TIM中断,DMA不使能。
----------------------------------------------------------
以上软件配置结束,自动生成代码即可。
main文件中添加:


#include "stdio.h"
#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]/

/**
* @brief Retargets the C library printf function to the USART.
* @param None
* @retval None
*/
PUTCHAR_PROTOTYPE
{
/[i] Place your implementation of fputc here [/i]/
/[i] e.g. write a character to the EVAL_COM1 and Loop until the end of transmission [/i]/
HAL_UART_Transmit(&huart3 , (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}

---------------------------------------为了能使用printf。
main()函数中添加:


/[i] USER CODE BEGIN 2 [/i]/
/[i][size=16]-3- Start the conversion process and enable interrupt [/size]#[size=16]#[size=16]#[size=16]#[size=16]#[size=16]#[/i]/ [/size][/size][/size][/size][/size]
if(HAL_ADC_Start_IT(&hadc1) != HAL_OK)
{
/[i] Start Conversation Error [/i]/
// Error_Handler();
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );
HAL_Delay (5000);
}
if(HAL_TIM_Base_Start(&htim8) != HAL_OK)
{
/[i] Counter Enable Error [/i]/
//Error_Handler();
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );
HAL_Delay (5000);
}

/[i] USER CODE END 2 [/i]/

/[i] USER CODE BEGIN 3 [/i]/
/[i] Infinite loop [/i]/
while (1)
{

HAL_Delay (1000);
HAL_GPIO_TogglePin (GPIOF,GPIO_PIN_6);
printf ("%d",s_value);
// HAL_ADC_Start_IT(&hadc1);
}
/[i] USER CODE END 3 [/i]/

-------------------------------------------------开启AD和TIM
底部添加:


/[i] USER CODE BEGIN 4 [/i]/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)
{
/[i] Get the converted value of regular channel [/i]/
uhADCxConvertedValue = HAL_ADC_GetValue(AdcHandle);
v_value += uhADCxConvertedValue;
count++;
if(count>=500) { s_value = v_value/500; v_value = 0; count=0; }
}

/[i] USER CODE END 4 [/i]/

---------------------------------------AD采集完成数据处理调用

其他文件不要变动。

下面是完整的main文件代码:


/[i] Includes ------------------------------------------------------------------[/i]/
#include "stm32f4xx_hal.h"

/[i] Private variables ---------------------------------------------------------[/i]/
ADC_HandleTypeDef hadc1;

TIM_HandleTypeDef htim8;

UART_HandleTypeDef huart3;

/[i] USER CODE BEGIN 0 [/i]/
#include "stdio.h"
#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]/

/**
* @brief Retargets the C library printf function to the USART.
* @param None
* @retval None
*/
PUTCHAR_PROTOTYPE
{
/[i] Place your implementation of fputc here [/i]/
/[i] e.g. write a character to the EVAL_COM1 and Loop until the end of transmission [/i]/
HAL_UART_Transmit(&huart3 , (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
/[i] Variable used to get converted value [/i]/
__IO uint16_t uhADCxConvertedValue = 0;
int32_t v_value;
int32_t s_value;
uint16_t count=0;
/[i] USER CODE END 0 [/i]/

/[i] Private function prototypes -----------------------------------------------[/i]/
static void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_ADC1_Init(void);
static void MX_TIM8_Init(void);
static void MX_USART3_UART_Init(void);

int main(void)
{

/[i] USER CODE BEGIN 1 [/i]/

/[i] USER CODE END 1 [/i]/

/[i] MCU Configuration----------------------------------------------------------[/i]/

/[i] Reset of all peripherals, Initializes the Flash interface and the Systick. [/i]/
HAL_Init();

/[i] Configure the system clock [/i]/
SystemClock_Config();

/[i] Initialize all configured peripherals [/i]/
MX_GPIO_Init();
MX_ADC1_Init();
MX_TIM8_Init();
MX_USART3_UART_Init();

/[i] USER CODE BEGIN 2 [/i]/
/[i][size=16]-3- Start the conversion process and enable interrupt [/size]#[size=16]#[size=16]#[size=16]#[size=16]#[size=16]#[/i]/ [/size][/size][/size][/size][/size]
if(HAL_ADC_Start_IT(&hadc1) != HAL_OK)
{
/[i] Start Conversation Error [/i]/
// Error_Handler();
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );
HAL_Delay (5000);
}
if(HAL_TIM_Base_Start(&htim8) != HAL_OK)
{
/[i] Counter Enable Error [/i]/
//Error_Handler();
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );
HAL_Delay (5000);
}

/[i] USER CODE END 2 [/i]/

/[i] USER CODE BEGIN 3 [/i]/
/[i] Infinite loop [/i]/
while (1)
{

HAL_Delay (1000);
HAL_GPIO_TogglePin (GPIOF,GPIO_PIN_6);
printf ("%d",s_value);
// HAL_ADC_Start_IT(&hadc1);
}
/[i] USER CODE END 3 [/i]/

}
/** System Clock Configuration
*/
static void SystemClock_Config(void)
{

RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;

__PWR_CLK_ENABLE();

__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 25;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
HAL_RCC_OscConfig(&RCC_OscInitStruct);

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1
|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);

}

/[i] ADC1 init function [/i]/
void MX_ADC1_Init(void)
{

ADC_ChannelConfTypeDef sConfig;
ADC_MultiModeTypeDef multimode;

/**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV2;
hadc1.Init.Resolution = ADC_RESOLUTION12b;
hadc1.Init.ScanConvMode = DISABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.NbrOfDiscConversion = 1;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T8_TRGO;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.EOCSelection = EOC_SINGLE_CONV;
HAL_ADC_Init(&hadc1);

/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_8;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);

/**Configure the ADC multi-mode
*/
multimode.Mode = ADC_MODE_INDEPENDENT;
multimode.TwoSamplingDelay = ADC_TWOSAMPLINGDELAY_5CYCLES;
HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode);

}

/[i] TIM8 init function [/i]/
void MX_TIM8_Init(void)
{

TIM_SlaveConfigTypeDef sSlaveConfig;
TIM_MasterConfigTypeDef sMasterConfig;

htim8.Instance = TIM8;
htim8.Init.Prescaler = 0;
htim8.Init.CounterMode = TIM_COUNTERMODE_UP;
htim8.Init.Period = 60;
htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim8.Init.RepetitionCounter = 0;
HAL_TIM_Base_Init(&htim8);

sSlaveConfig.SlaveMode = TIM_SLAVEMODE_TRIGGER;
sSlaveConfig.InputTrigger = TIM_TS_ITR0;
HAL_TIM_SlaveConfigSynchronization(&htim8, &sSlaveConfig);

sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&htim8, &sMasterConfig);

}

/[i] USART3 init function [/i]/
void MX_USART3_UART_Init(void)
{

huart3.Instance = USART3;
huart3.Init.BaudRate = 9600;
huart3.Init.WordLength = UART_WORDLENGTH_8B;
huart3.Init.StopBits = UART_STOPBITS_1;
huart3.Init.Parity = UART_PARITY_NONE;
huart3.Init.Mode = UART_MODE_TX_RX;
huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart3.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&huart3);

}

/** Configure pins as
* Analog
* Input
* Output
* EVENT_OUT
* EXTI
*/
void MX_GPIO_Init(void)
{

GPIO_InitTypeDef GPIO_InitStruct;

/[i] GPIO Ports Clock Enable [/i]/
__GPIOF_CLK_ENABLE();
__GPIOH_CLK_ENABLE();
__GPIOB_CLK_ENABLE();

/[i]Configure GPIO pin : PF6 [/i]/
GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

}

/[i] USER CODE BEGIN 4 [/i]/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)
{
/[i] Get the converted value of regular channel [/i]/
uhADCxConvertedValue = HAL_ADC_GetValue(AdcHandle);
v_value += uhADCxConvertedValue;
count++;
if(count>=500) { s_value = v_value/500; v_value = 0; count=0; }
}

/[i] USER CODE END 4 [/i]/ 查看全部
stm32cube中文教程:AD用TIM8定时采集,uart3输出
arm片子stm32f407ZGT,用ADC1,TIM8,UART3,。
ad脚PB0,uart脚PB10和11,PF6输出led灯。
晶振25M,时钟168M。
stm32cubemx软件设置:
uart9600,8,0,1,不使能uart中断,TX:PULL_up,fast。RX:NO PULL_UP,fast
DMA不使能。
ADC设置:修改了continuous conversion mode:enable;end of conversion selection :Eoc flag signle channel

External Trigger conversion Edge : Trigger detection on the rising edge
External Trigger Conversion Source : Time 8 Trigger Out event
其余的默认即可。
ADC中断不使能。
TIme8定时设置:
Prescaler(psc - 16 bits value) : 0
counter mode : UP
counter Period(autoreload register - 16 bits value) : 60
internal clock division (CDK) : NO Division
Repetition counter(RCR - 8bits value) : 0
slave mode controller : trigger mode
master/slave mode : Disable
trigger event selection : Update enent
不使能任何TIM中断,DMA不使能。
----------------------------------------------------------
以上软件配置结束,自动生成代码即可。
main文件中添加:


#include "stdio.h"
#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]/

/**
* @brief Retargets the C library printf function to the USART.
* @param None
* @retval None
*/
PUTCHAR_PROTOTYPE
{
/[i] Place your implementation of fputc here [/i]/
/[i] e.g. write a character to the EVAL_COM1 and Loop until the end of transmission [/i]/
HAL_UART_Transmit(&huart3 , (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}

---------------------------------------为了能使用printf。
main()函数中添加:


/[i] USER CODE BEGIN 2 [/i]/
/[i][size=16]-3- Start the conversion process and enable interrupt [/size]#[size=16]#[size=16]#[size=16]#[size=16]#[size=16]#[/i]/ [/size][/size][/size][/size][/size]
if(HAL_ADC_Start_IT(&hadc1) != HAL_OK)
{
/[i] Start Conversation Error [/i]/
// Error_Handler();
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );
HAL_Delay (5000);
}
if(HAL_TIM_Base_Start(&htim8) != HAL_OK)
{
/[i] Counter Enable Error [/i]/
//Error_Handler();
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );
HAL_Delay (5000);
}

/[i] USER CODE END 2 [/i]/

/[i] USER CODE BEGIN 3 [/i]/
/[i] Infinite loop [/i]/
while (1)
{

HAL_Delay (1000);
HAL_GPIO_TogglePin (GPIOF,GPIO_PIN_6);
printf ("%d",s_value);
// HAL_ADC_Start_IT(&hadc1);
}
/[i] USER CODE END 3 [/i]/

-------------------------------------------------开启AD和TIM
底部添加:


/[i] USER CODE BEGIN 4 [/i]/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)
{
/[i] Get the converted value of regular channel [/i]/
uhADCxConvertedValue = HAL_ADC_GetValue(AdcHandle);
v_value += uhADCxConvertedValue;
count++;
if(count>=500) { s_value = v_value/500; v_value = 0; count=0; }
}

/[i] USER CODE END 4 [/i]/

---------------------------------------AD采集完成数据处理调用

其他文件不要变动。

下面是完整的main文件代码:


/[i] Includes ------------------------------------------------------------------[/i]/
#include "stm32f4xx_hal.h"

/[i] Private variables ---------------------------------------------------------[/i]/
ADC_HandleTypeDef hadc1;

TIM_HandleTypeDef htim8;

UART_HandleTypeDef huart3;

/[i] USER CODE BEGIN 0 [/i]/
#include "stdio.h"
#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]/

/**
* @brief Retargets the C library printf function to the USART.
* @param None
* @retval None
*/
PUTCHAR_PROTOTYPE
{
/[i] Place your implementation of fputc here [/i]/
/[i] e.g. write a character to the EVAL_COM1 and Loop until the end of transmission [/i]/
HAL_UART_Transmit(&huart3 , (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
/[i] Variable used to get converted value [/i]/
__IO uint16_t uhADCxConvertedValue = 0;
int32_t v_value;
int32_t s_value;
uint16_t count=0;
/[i] USER CODE END 0 [/i]/

/[i] Private function prototypes -----------------------------------------------[/i]/
static void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_ADC1_Init(void);
static void MX_TIM8_Init(void);
static void MX_USART3_UART_Init(void);

int main(void)
{

/[i] USER CODE BEGIN 1 [/i]/

/[i] USER CODE END 1 [/i]/

/[i] MCU Configuration----------------------------------------------------------[/i]/

/[i] Reset of all peripherals, Initializes the Flash interface and the Systick. [/i]/
HAL_Init();

/[i] Configure the system clock [/i]/
SystemClock_Config();

/[i] Initialize all configured peripherals [/i]/
MX_GPIO_Init();
MX_ADC1_Init();
MX_TIM8_Init();
MX_USART3_UART_Init();

/[i] USER CODE BEGIN 2 [/i]/
/[i][size=16]-3- Start the conversion process and enable interrupt [/size]#[size=16]#[size=16]#[size=16]#[size=16]#[size=16]#[/i]/ [/size][/size][/size][/size][/size]
if(HAL_ADC_Start_IT(&hadc1) != HAL_OK)
{
/[i] Start Conversation Error [/i]/
// Error_Handler();
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );
HAL_Delay (5000);
}
if(HAL_TIM_Base_Start(&htim8) != HAL_OK)
{
/[i] Counter Enable Error [/i]/
//Error_Handler();
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );
HAL_Delay (5000);
}

/[i] USER CODE END 2 [/i]/

/[i] USER CODE BEGIN 3 [/i]/
/[i] Infinite loop [/i]/
while (1)
{

HAL_Delay (1000);
HAL_GPIO_TogglePin (GPIOF,GPIO_PIN_6);
printf ("%d",s_value);
// HAL_ADC_Start_IT(&hadc1);
}
/[i] USER CODE END 3 [/i]/

}
/** System Clock Configuration
*/
static void SystemClock_Config(void)
{

RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;

__PWR_CLK_ENABLE();

__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 25;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
HAL_RCC_OscConfig(&RCC_OscInitStruct);

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1
|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);

}

/[i] ADC1 init function [/i]/
void MX_ADC1_Init(void)
{

ADC_ChannelConfTypeDef sConfig;
ADC_MultiModeTypeDef multimode;

/**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV2;
hadc1.Init.Resolution = ADC_RESOLUTION12b;
hadc1.Init.ScanConvMode = DISABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.NbrOfDiscConversion = 1;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T8_TRGO;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.EOCSelection = EOC_SINGLE_CONV;
HAL_ADC_Init(&hadc1);

/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_8;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);

/**Configure the ADC multi-mode
*/
multimode.Mode = ADC_MODE_INDEPENDENT;
multimode.TwoSamplingDelay = ADC_TWOSAMPLINGDELAY_5CYCLES;
HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode);

}

/[i] TIM8 init function [/i]/
void MX_TIM8_Init(void)
{

TIM_SlaveConfigTypeDef sSlaveConfig;
TIM_MasterConfigTypeDef sMasterConfig;

htim8.Instance = TIM8;
htim8.Init.Prescaler = 0;
htim8.Init.CounterMode = TIM_COUNTERMODE_UP;
htim8.Init.Period = 60;
htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim8.Init.RepetitionCounter = 0;
HAL_TIM_Base_Init(&htim8);

sSlaveConfig.SlaveMode = TIM_SLAVEMODE_TRIGGER;
sSlaveConfig.InputTrigger = TIM_TS_ITR0;
HAL_TIM_SlaveConfigSynchronization(&htim8, &sSlaveConfig);

sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&htim8, &sMasterConfig);

}

/[i] USART3 init function [/i]/
void MX_USART3_UART_Init(void)
{

huart3.Instance = USART3;
huart3.Init.BaudRate = 9600;
huart3.Init.WordLength = UART_WORDLENGTH_8B;
huart3.Init.StopBits = UART_STOPBITS_1;
huart3.Init.Parity = UART_PARITY_NONE;
huart3.Init.Mode = UART_MODE_TX_RX;
huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart3.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&huart3);

}

/** Configure pins as
* Analog
* Input
* Output
* EVENT_OUT
* EXTI
*/
void MX_GPIO_Init(void)
{

GPIO_InitTypeDef GPIO_InitStruct;

/[i] GPIO Ports Clock Enable [/i]/
__GPIOF_CLK_ENABLE();
__GPIOH_CLK_ENABLE();
__GPIOB_CLK_ENABLE();

/[i]Configure GPIO pin : PF6 [/i]/
GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

}

/[i] USER CODE BEGIN 4 [/i]/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)
{
/[i] Get the converted value of regular channel [/i]/
uhADCxConvertedValue = HAL_ADC_GetValue(AdcHandle);
v_value += uhADCxConvertedValue;
count++;
if(count>=500) { s_value = v_value/500; v_value = 0; count=0; }
}

/[i] USER CODE END 4 [/i]/