完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
本篇文章主要是学习以M3内核的STM32的串口的寄存器的配置,为什么要学习寄存器,而不利用库函数呢?我只能说为了让学的知识更加牢固吧!当然,你可以直接去利用库函数(库函数版点击:单片机中UART的那些事儿),但是如果你能认真读完本篇博客,分析的过程就是不断提高的过程,加油!你会对知识豁然开朗!加油吧!
串口作为 MCU 的重要外部接口,也是软件开发重要的调试手段,其重要性不言而喻。现在基本上所有的 MCU 都会带有串口。支持同步单线通信和半双工单线通讯。接下来将从寄存器层面,来设置串口,以达到最基本的通信功能。功能是主要利用串口 1 不停的打印信息到电脑。 STM32最多可以提供5路串口,其串口配置主要有以下步骤: 1、串口时钟使能;2、串口复位即结束复位;3、串口波特率设置;4、串口控制;5、数据发送和接收,下面就从这5个方面分别进行配置寄存器。 一、串口时钟使能 首先明确的是串口 1 的时钟使能是在 APB2ENR 寄存器里进行,找到 APB2ENR 寄存器数据描述: 其次第14位就是控制串口1的时钟使能,所以只需要将其置为1,所以程序为: RCC->APB2ENR|=1<<14;//使能串口1的时钟 二、串口时钟复位 首先明确的是串口 1 的时钟使能是在 APB2RSTR 寄存器里进行,找到 APB2RSTR 寄存器数据描述: 其次第14位就是控制串口1的时钟复位,所以只需要将其置为1,所以程序为: RCC->APB2RSTR|=1<<14;//复位串口1的时钟 三、串口波特率设置 STM32 的每个串口都有一个自己独立的波特率寄存器 USART_BRR,通过设置该寄存器就可以达到配置不同波特率的目的。 从上图中可以看出USART_BRR 的最低 4 位(位[3:0])用来存放小数部分 DIV_Fraction,紧接着的 12 位(位[15:4])用来存放整数部分 DIV_Mantissa,最高 16 位未使用。而波特率的计算公式为: 上式中, 是给串口的时钟(PCLK1 用于 USART2、3、4、5,PCLK2 用于 USART1);USARTDIV 是一个无符号定点数。我们只要得到 USARTDIV 的值,就可以得到串口波特率寄存器 USART1->BRR 的值,反过来,我们得到 USART1->BRR 的值,也可以推导出 USARTDIV的值。但我们更关心的是如何从 USARTDIV 的值得到 USART_BRR 的值,因为一般我们知道 的是波特率,和 PCLKx 的时钟,要求的就是 USART_BRR 的值。 假设我们的串口 1 要设置为 115200 的波特率,而 PCLK2 的时钟为 72M。所以带入上式可得:USARTDIV=72000000/(115200*16)= 39.0625,所以小数部分为:0.0625,整数部分为:39,所以可以知道换成16进制(不懂进制请点击:C语言中数值常量的“那些事”):DIV_Fraction=16*0. 0625=1=0X01;DIV_Mantissa=39=0X27; 所以程序可以简单的写成: USART1->BRR=0X27; // 波特率设置 当然以上的计算过程程序为: float temp; u16 mantissa; u16 fraction; temp=(float)(pclk2*1000000)/(bound*16);//得到 USARTDIV mantissa=temp; //得到整数部分 fraction=(temp-mantissa)*16; //得到小数部分 mantissa<<=4;//因为后4位是要存放小数的,所以左移4位 mantissa+=fraction;//得到应该存放进BRR的数 四、串口控制 首先需要知道STM32的每个串口都有3个控制寄存器(USART_CR1~3)控制,串口的很多配置都是通过这 3 个寄存器来设置的。这里我们只要用到 USART_CR1 就可以实现我们的功能。 第13位UE使能串口(任何串口在应用的时候都必需将其置“1”);第12位M设置字长,当这位为“0”的时候设置串口位8个字长外加n个停止位,这n个停止位在寄存器USART_CR2中第[13:12]位来决定。PCE为奇偶校验位使能位设置为“0”则禁止校验,否则使能校验。PS是校验选择位,设置为“0”则为偶校验,否则为奇校验。PEIE:PE(校验错误)中断使能,该位由软件设置或清除,定义:0(禁止产生中断),1(当USART_SR中的PE为’1’时,产生USART中断)。TXEIE发送缓冲区空中断使能,(手动),定义:0(禁止产生中断),1(当USART_SR中的TXE为’1’时,产生USART中断)。TCIE发送完成中断使能,(手动),定义:0(禁止产生中断)1(当USART_SR中的TC为’1’时,产生USART中断)。RXNEIE接收缓冲区非空中断使能,(手动),定义:0(禁止产生中断),1(当USART_SR中的ORE或者RXNE为’1’时,产生USART中断)。TE为发送使能位,设置为“1”将开启串口的发送功能。RE为接收使能位,用法同TE。 在这个例子的程序为: USART1->CR1|=1<<8; //PE中断使能 USART1->CR1|=1<<5; //接收缓冲区非空中断使能 5、数据发送和接收 STM32 的发送与接收是通过数据寄存器 USART_DR 来实现的,这是一个双寄存器,包含了 TDR 和 RDR。当向该寄存器写数据的时候,串口就会自动发送,当收到数据的时候,也是存在该寄存器内。 DR[8:0]为串口数据,包含了发送或接收的数据。由于它是由两个寄存器组成的,一个给发送用(TDR),一个给接收用(RDR),该寄存器兼具读和写的功能。 程序为:USART1->DR=USART_RX_BUF[t];//就是发送一个字节到串口,通过直接操作寄存器来实现的 while((USART1->SR&0X40)==0);//等待发送结束我们在写了一个字节在 USART1->DR 之后,要检测这个数据是否已经被发送完成了,通过检测USART1->SR 的第 6 位,是否为 1 来决定是否可以开始第二个字节的发送。 uart_init 函数参考程序: /初始化 IO 串口 1 //pclk2:PCLK2 时钟频率(Mhz) //bound:波特率 void uart_init(u32 pclk2,u32 bound) { float temp; u16 mantissa; u16 fraction; temp=(float)(pclk2*1000000)/(bound*16);//得到 USARTDIV mantissa=temp; //得到整数部分 fraction=(temp-mantissa)*16; //得到小数部分 mantissa<<=4; mantissa+=fraction; RCC->APB2ENR|=1<<2; //使能 PORTA 口时钟 RCC->APB2ENR|=1<<14; //使能串口时钟 GPIOA->CRH&=0XFFFFF00F;//IO 状态设置 GPIOA->CRH|=0X000008B0;//IO 状态设置 RCC->APB2RSTR|=1<<14; //复位串口 1 RCC->APB2RSTR&=~(1<<14);//停止复位 //波特率设置 USART1->BRR=mantissa; // 波特率设置 USART1->CR1|=0X200C; //1 位停止,无校验位. #if EN_USART1_RX //如果使能了接收 //使能接收中断 USART1->CR1|=1<<5; //接收缓冲区非空中断使能 MY_NVIC_Init(3,3,USART1_IRQn,2);//组 2,最低优先级 #endif } USART1中断程序: void USART1_IRQHandler(void) { u8 res; if(USART1->SR&(1<<5))//接收到数据 { res=USART1->DR; if((USART_RX_STA&0x80)==0)//接收未完成 { if(USART_RX_STA&0x40)//接收到了0x0d { if(res!=0x0a)USART_RX_STA=0;//接收错误,重新开始 else USART_RX_STA|=0x80; //接收完成了 }else //还没收到0X0D { if(res==0x0d)USART_RX_STA|=0x40; else { USART_RX_BUF[USART_RX_STA&0X3F]=res; USART_RX_STA++; if(USART_RX_STA>63)USART_RX_STA=0;//接收数据错误,重新开始接收 } } } } } test.c程序: #include "sys.h" #include "delay.h" #include "usart.h" #include "led.h" int main(void) { u16 t; u16 len; u16 times=0; Stm32_Clock_Init(9); //系统时钟设置 uart_init(72,115200); //串口初始化为 115200 delay_init(72); //延时初始化 LED_Init(); //初始化与 LED 连接的硬件接口 while(1) { if(USART_RX_STA&0x8000) { len=USART_RX_STA&0x3FFF;//得到此次接收到的数据长度 printf("rn 您发送的消息为:rnrn"); for(t=0;t USART1->DR=USART_RX_BUF[t]; while((USART1->SR&0X40)==0);//等待发送结束 } printf("rnrn");//插入换行 USART_RX_STA=0; }else { times++; if(times%5000==0) { printf("rn 关注公众号:科技眼 串口实验rn"); printf("关注公众号:科技眼rnrn"); } if(times%200==0)printf("请输入数据,以回车键结束rn"); if(times%30==0)LED0=!LED0;//闪烁 LED,提示系统正在运行. delay_ms(10); } } } 好了,就介绍到这,其实主要是介绍学习的方法,如何去分析,学会后,就可以很快的去接触一款新的控制器芯片。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1602 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1536 浏览 1 评论
967 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
680 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1579 浏览 2 评论
1860浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
640浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
513浏览 3评论
526浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
500浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-19 05:22 , Processed in 0.671437 second(s), Total 79, Slave 62 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号