一、首先开发板上关于串口1的引脚配置已经配置好了,位置在SYSTEM的 usart.c 文件中(注意:只配置了串口1的,其他使用时需要自己配置)
重要的是明白配置的参数都是什么意思,针对实现不同的串口功能有什么影响
二、主要是结合串口的固件库函数使用,熟悉固件库中各个函数的使用方法
串口配置:
1.三个结构体
2.使能外设引脚时钟,使能串口外设时钟
3.F407每个引脚功能很多,所以需要配置引脚的功能模式(引脚的各个配置对于引脚的输入输出功能都有什么影响,在此暂且默认为例程的配置,其他串口不同的配置后续再做研究)
进行引脚初始化设置
4.复用功能配置,将引脚的功能定为串口外设要使用的引脚
5.对串口外设需要实现的功能进行相应的参数配置
注意有些硬件设备上USB串口和USART引脚并没有连接起来,需要通过跳线帽连接
这样连接,可以实现通过USB口下载程序以及传输数据
这张图就是其基本原理,
需要配置的参数
:
① 串口时钟使能,GPIO 时钟使能
② 设置引脚复用器映射
③ GPIO 端口初始化设置
④ 串口参数初始化
⑤ 初始化 NVIC 并且开启串口中断,配置中断参数
这个位置要注意怎样开启中断的
⑥ 使能串口
整个配置的思路在库函数书中有详细的描述
必须在 usart.h 里面设置
EN_USART1_RX 为 1(默认设置就是 1 的)。该函数才会配置中断使能,以及开启串口 1 的 NVIC
中断。这里我们把串口 1 中断放在组 2,优先级设置为组 2 里面的最低
(这个位置中断的优先级分组又表示什么意思,有什么影响呢?有几种配置方式)
串口 1 的中断服务函数 USART1_IRQHandler
USART_SendData(USART1, USART_RX_BUF[t]); //向串口 1 发送数据
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);
第一句,其实就是发送一个字节到串口。第二句呢,就是我们在我们发送一个数据到串口
之后,要检测这个数据是否已经被发送完成了
1.波特率 计算公式
2.8位数据位
3.1个停止位
4.无奇偶校验
5.无硬件流控制
6.允许收发数据
在主函数中初始化串口的时候报错 函数的参数太少
原因是:串口初始化没有给波特率 ![在这里插入图片描述](https://img-blog.csdnimg.cn/71b351bcdb9647999c5e937452f891f6.png)
USART 框图 模式配置应该是必须要了解的内容
总结下调试串口遇到的问题吧:
首先可以实现在中断中串口助手发送接收的功能,其次在主函数中实现单个字符发送,遇到了:明明只发送了一个字符但是串口助手中发送了3个字符的现象,并且有些时候串口助手还会出现乱码的现象,基于出现这个问题开始思考,最原始的思路是:想要寻找一份可以实现全部功能的完美代码对照看自己是不是什么地方配置错了,但是这个方向很学生思维,非常不可取,这不是真正可以解决问题的方法,解决的方法在于基于自己的代码,一步步调试看每一步的结果,并且调试也不是去看寄存器的值,实际上这并没有任何作用,而是学会真正读懂所涉及到的实现功能函数的原理,不断去理解。
解决开始遇到的问题:三个字符的原因可能是因为电脑硬件上自己的问题,实际上只发送了一个字符
乱码的问题,其中没有 while(1);乱码的原因是因为Keil将所编写的语言转化为汇编语言后,在后续又加上了从头开始运行代码,而while(1);的功能就是不断执行当前正在执行的代码,不会让程序从头开始运行。
第二个乱码的问题就是发送 5 和 ‘ 5 ’ 的区别, 发送的字符都是按照 ASCII 上来执行的,5 是0x05 ’ 5 ’ 是 0x31,并且串口只能发送1字节的数据,且如果不想令其出现乱码的情况,就只能发送ASCII表上没有特殊功能的字符
由ASCII表可知,数字5代表的字符是enq,串口是没办法识别这个字符的,所以会出现乱码的现象,但是如果是以十六进制的形式显示的话,对应的值就是0x05,是正确的
另外传参数的问题,所定义变量是无符号短整型,实参是给形参传值的,只是一个赋值的作用,而不是需要判断实参的数据类型是什么,实参的值最终都要转化为十六进制赋值给形参,(这个位置还是没有很明白,十六进制的值最终传递给了无符号整型,为什么可以这样传)
发送函数中,USARTx->DR = (Data & (uint16_t)0x01FF);
&0x01FF目的是取数据的第九位,原因是硬件上只认为低九位是有效位,这个可以看参考手册上寄存器的位来确定。
如上图:串口连续发送三个字符,但最终只接收到了C,原因是串口发送数据很快,在还没有确定前一个发送完成的情况下,下一个数据已经到达数据缓冲区,所以最终只发送了C,现在就需要一个语句来检验上一个字符已经发送完成,再接着发送下一条语句
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
检测标志位TXE发送数据寄存器为0时,数据还没有被转移到数据寄存器,RESET为0,意思就是还没有被移位到数据寄存器中的时候,就会一直处于这个循环当中,,当转移到寄存器中的时候,就跳出循环执行下一语句
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
发送完成寄存器,发送完成为1,SET为1,没有发送完成的时候,逻辑表达语句为假,跳出循环,执行下一条语句
两条语句的作用是一样的
就感觉很神奇,自己想了很长时间都没有想明白的问题,经大师点拨,代码马上就成功了
后续进行的串口中断控制LED亮灭的功能:
使用LED,LED就一定会有对应的IO口
首先配置led.c led.h 中的内容,具体是依靠例程实现的
其次是在主函数中实现亮灭控制,是依靠中断标志位来实现的,注意要添加.c文件,头文件路径,主函数中添加.h文件,usart.c 中添加 led.h文件,否则可能出现LED0等变量没有定义的问题,还有一个标志位的问题,在用 extern 在主函数中引用标志位的时候注意不要有给这个变量赋值的部分,大错特错
extern int flag=0; 这种,标志位在usart.c中已经赋值了,这样就相当于再次赋值
串口的问题到此先暂时结束了,马不停蹄奔向下一个节点