stm32F103RCT6提供5路串口。串口的使用,只要开启串口时钟,设置相应的I/O口的模式,然后配置下波特率、数据位长度、奇偶校验等信息,即可使用。

1.串口的配置步骤

①串口时钟使能

  APB2外设时钟使能寄存器(RCC_APB2ENR)

置1开启。清0关闭。

第14位对串口1的时钟使能

  Eg:RCC->APB2ENR| = 1<<14;  //使能串口1时钟

除串口1的时钟使能在RCC_APB2ENR寄存器,其余的时钟使能位在寄存器RCC_APB1ENR寄存器,而APB2(72M)的频率一般是APB1(36M)的一倍。

  APB1外设时钟使能寄存器(RCC_APB1ENR)

20-17位 串口5-2时钟使能

  Eg:RCC->APB1ENR| = 1<<17;  //使能串口2时钟

②串口复位

  一般在系统刚开始配置外设时,都会先执行复位该外设的操作,而复位后要将其结束复位。

  串口复位主要在寄存器RCC_APB2RSTR(串口1的复位)和寄存器RCC_APB1RSTR(串口2-5的复位)。

  APB2外设复位寄存器 (RCC_APB2RSTR)

置1复位,清0无作用。

第14位是串口1复位

  Eg:RCC->APB2RSTR |= 1<<14;  //复位串口1

     RCC->APB2RSTR &= ~(1<<14);  //停止复位

  APB1外设复位寄存器 (RCC_APB1RSTR)

置1复位,清0无作用。

20-17位 串口5-2复位

  Eg: RCC->APB1RSTR |= 1<<17;  //复位串口2

      RCC->APB1RSTR &= ~(1<<17);  //停止复位

③串口波特率设置

  波特比率寄存器()

  关于波特率设置在函数void uart_init(u32 pclk2,u32 bound)里已经设置好,并且封装在usart.c文件里面可以直接调用。

④串口控制

  stm32的每个串口都有3个控制寄存器USART_CR1~3控制

  控制寄存器1(USART_CR1)

  该寄存器32~14位保留,第13位使能串口(任何串口在应用的时候都必需将其置“1”)第12位设置字长,当这位为“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。

  控制寄存器2(USART_CR2)

Eg:USART1->CR1|=0X200C;  //1位停止,无校验位. 0X200C=0010 0000 0000 1100B

设置成使能串口8个字长1个停止位(USART_CR2中[13:12]默认为“0”)禁止校验,禁止校验所有中断,使能发送和接收。

⑤数据的发送和接收

  数据寄存器(USART_DR)

发送数据缓存寄存器(向它写数据它会自动发送数据),当接收到数据时则存放接收的数据

⑥串口状态

  状态寄存器(USART_SR)

RXNE(读数据寄存器非空),当该位被置1时,即提示已经有数据被接收,可以读取。我们应尽快读取USART_DR,通过读USART_DR可以将该位清0,也可以向该位写0直接清除。

TC(发送完成),当该位被置位时,表示USART_DR内的数据以及被发送完成了。如果设置了这个位的中断,则会产生中断。该位两种清0方式:①读USART_DR ②向该位写0直接清除

2.关于波特率的计算

void uart_init(u32 pclk2,u32 bound) pclk2是系统时钟平率。bound需要设置的波特率,例如9600、115200等。

参考1.③中的USART_BRR寄存器。

STM32串口波特率的计算公式如下:

  Tx/Rx波特率 = fPCLKx / (16*USARTDIV)

  fPCLKx是给串口的时钟(PCLK1用于USART2-5,PCLK2用于USART1)

  USARTDIV是一个无符号定点数,得到USARTDIV,可得USART1->BRR值;可得USART1->BRR值,可推USARTDIV。

  Eg:串口1要设置为9600波特率,而PCLK2时钟为72MHz。

    USARTDIV = 72000000 / (16 * 9600) = 468.75

   那么得到:DIV_Fraction(小数部分) = 16*0.75 = 12 = 0x0C;  DIV_Mantissa(整数部分) = 468 = 0x1D4

     这样就得到了USART1->BRR = 0x1D4C。设置1.③中的USART_BRR寄存器值为0x1D4C,即可得到9600的波特率。

3.USART1

void uart_init(u32 pclk2,u32 bound)
void USART1_IRQHandler(void)

两个函数已经封装在usart.c中可直接调用

 //初始化I/O 串口1
//pclk2:PCLK2时钟频率(Mhz)
//bound:波特率 void uart_init(u32 pclk2,u32 bound)
{
float temp;
u16 mantissa;
u16 fraction;
temp=(float)(pclk2*)/(bound*);//得到USARTDIV
mantissa=temp; //得到整数部分
fraction=(temp-mantissa)*; //得到小数部分
mantissa<<=;
mantissa+=fraction;
RCC->APB2ENR|=<<; //使能PORTA时钟
RCC->APB2ENR|=<<; //使能串口时钟
GPIOA->CRH&=0XFFFFF00F;//IO状态设置 PA9 PA10
GPIOA->CRH|=0X000008B0;//IO状态设置 RCC->APB2RSTR|=<<; //复位串口1
RCC->APB2RSTR&=~(<<);//停止复位
//波特率设置
USART1->BRR=mantissa; // 波特率设置
USART1->CR1|=0X200C; //1位停止 无校验位
#if EN_USART1_RX //如果使能了接收
//使能接收中断
USART1->CR1|=<<; //PE中断使能
USART1->CR1|=<<; //接收缓冲区非空中断使能
MY_NVIC_Init(,,USART1_IRQn,);//组2 最低优先级
#endif
}

当需要使用串口接收的时候,要在usart.h里面设置EN_USART1_RX为1即可。不使用时设置为0。

//uart.h
#ifndef __USART_H
#define __USART_H
#include "sys.h"
#include "stdio.h"
#define USART_REC_LEN 200 //定义最大接收字节数 200
#define EN_USART1_RX 1 //使能1 禁止0 串口1接收 extern u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
extern u16 USART_RX_STA; //接收状态标记 void uart_init(u32 pclk2,u32 bound); #endif
 #if EN_USART1_RX   //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误
u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15, 接收完成标志
//bit14, 接收到0x0d
//bit13~0, 接收到的有效字节数目
u16 USART_RX_STA=; //接收状态标记 void USART1_IRQHandler(void)
{
u8 res;
#ifdef OS_CRITICAL_METHOD //如果OS_CRITICAL_METHOD定义了,说明使用ucosII了.
OSIntEnter();
#endif
if(USART1->SR&(<<))//接收到数据
{
res=USART1->DR;
if((USART_RX_STA&0x8000)==)//接收未完成
{
if(USART_RX_STA&0x4000)//接收到了0x0d
{
if(res!=0x0a)USART_RX_STA=;//接收错误,重新开始
else USART_RX_STA|=0x8000; //接收完成了
}else //还没收到0X0D
{
if(res==0x0d)USART_RX_STA|=0x4000;
else
{
USART_RX_BUF[USART_RX_STA&0X3FFF]=res;
USART_RX_STA++;
if(USART_RX_STA>(USART_REC_LEN-))USART_RX_STA=;//接收数据错误,重新开始接收
}
}
}
}
#ifdef OS_CRITICAL_METHOD //如果OS_CRITICAL_METHOD定义了,说明使用ucosII了.
OSIntExit();
#endif
}
#endif

4.关于void USART1_IRQHandler(void)函数

  该函数时串口1的中断响应函数,当串口1发生相应中断后,就会跳到该函数执行。这里设计的接收协议:通过这个函数,配合一个数组USART_RX_BUF[]、一个接收状态寄存器USART_RX_STA(全局变量,作者自行添加)实现对串口数据的接受管理。USART_RX_BUF[]大小由USART_REC_LEN定义,即不超过USART_REC_LEN个字节。

5.应用测试

 #include "sys.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "key.h" int main(void)
{
u8 t;
u8 len;
u16 times=;
Stm32_Clock_Init(); //系统时钟设置
delay_init(); //延时初始化
uart_init(,); //串口初始化为9600
LED_Init(); //初始化与LED连接的硬件接口
while()
{
if(USART_RX_STA&0x8000) //1000 0000 0000 0000 接收成功
{
len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
printf("\r\n您发送的消息为:\r\n");
for(t=;t<len;t++)
{
USART1->DR=USART_RX_BUF[t];
while((USART1->SR&0X40)==);//等待发送结束
}
printf("\r\n\r\n");//插入换行
USART_RX_STA=;
}else
{
times++;
if(times%==)printf("请输入数据,以回车键结束\r\n");
if(times%==)LED0=!LED0;//闪烁LED,提示系统正在运行.
delay_ms();
}
}
}

stm32寄存器版学习笔记02 串口通信的更多相关文章

  1. stm32寄存器版学习笔记07 ADC

    STM32F103RCT有3个ADC,12位主逼近型模拟数字转换器,有18个通道,可测量16个外部和2个内部信号源.各通道的A/D转换可以单次.连续.扫描或间断模式执行. 1.通道选择 stm32把A ...

  2. stm32寄存器版学习笔记06 输入捕获(ETR脉冲计数)

    STM32外部脉冲ETR引脚:TIM1-->PA12;TIMER2-->PA0:TIMER3-->PD2;TIMER4-->PE0… 1.TIM2 PA0计数 配置步骤 ①开启 ...

  3. stm32寄存器版学习笔记05 PWM

    STM32除TIM6和TIM7外都可以产生PWM输出.高级定时器TIM1和TIM8可以同时产生7路PWM,通用定时器可以产生4路PWM输出. 1.TIM1 CH1输出PWM配置步骤 ①开启TIM1时钟 ...

  4. stm32寄存器版学习笔记03 外部中断

    stm32的每个I/O口都可以作为中断输入,要把I/O口设置为外部中断输入,必须将I/O口设置为上拉/下拉输入 或 浮空输入(但浮空的时候外部一定要带上拉或下拉电阻,否则可能导致 中断不停的触发),干 ...

  5. stm32寄存器版学习笔记08 DMA

    DMA(Direct Memory Access),直接存储器访问.DMA传输方式无需CPU直接控制传输,通过硬件为RAM与I/O设备开辟一条直接传送数据的通路,使CPU效率大大提高.stm32f10 ...

  6. stm32寄存器版学习笔记04 定时计数器中断

    STM32共有8个定时计数器,其中TIME1和TIME8是高级定时器,TIME2~TIME5是通用定时器,TIME6和TIME7是基本定时器.以TIME3为例总结定时计数器的基本用法. 1.TIM3的 ...

  7. stm32寄存器版学习笔记10 SPI

    SPI(Serial Peripheral Interface),串行外围设备接口.SPI是一种高速的.全双工.同步的通信总线. SPI接口一般使用4条线通信: MISO 主设备数据输入,从设备数据输 ...

  8. stm32寄存器版学习笔记01 GPIO口的配置(LED、按键)

    STM32的I/O口可以由软件配置成如下8种模式:输入浮空.输入上拉.输入下拉.模拟输入.开漏输出.推挽输出.推挽式复用功能及开漏复用功能.每个I/O口由7个寄存器来控制:配置模式的端口配置寄存器CR ...

  9. stm32寄存器版学习笔记09 IIC

    I²C(Inter-Integrated Circuit)总线是一种两线式串行总线,用于连接微控制器及其外设,是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据. IIC总线在传送数据过程中 ...

随机推荐

  1. SpringMvc 笔记

    整理出来是 SpringMvc 笔记 方便以后查询 框架太多了 不经常使用 忘记的可能性很大 自己整理一套笔记 一看就明白了 1 对比 原始请求响应流程 1 发送请求 --> 2 控制层 --& ...

  2. LightOJ 1341 Aladdin and the Flying Carpet(唯一分解定理)

    http://lightoj.com/volume_showproblem.php?problem=1341 题意:给你矩形的面积(矩形的边长都是正整数),让你求最小的边大于等于b的矩形的个数. 思路 ...

  3. location的部分属性

    http://www.w3school.com.cn/jsref/dom_obj_location.asp location.host 可以设置或返回主机名和当前url的端口    www.w3sch ...

  4. python 中str format 格式化数字补0方法

      >>> "{0:03d}".format(1)'001'>>> "{0:03d}".format(10)'010'> ...

  5. uva10002凸包重心

    把每个三角形看成一个质点,坐标就是各自的重心, #include<map> #include<set> #include<cmath> #include<qu ...

  6. Codeforces Round #409

    第一题很水但是wa了一发,因为没考虑K前面是K的情况 #include<map> #include<set> #include<cmath> #include< ...

  7. ORM--------Hibernate、Mybatis与Spring Data的区别

    1.概念: Hibernate :Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库.着力点对象 ...

  8. 搭建多master的saltstack环境

    0.16.0版本的发布,带来了minion可以连接多Master的特性. 这种方式称为多master( multi-master )配置, 使环境中的SaltStack冗余.在这种配置下,Salt M ...

  9. 转载:【Oracle 集群】RAC知识图文详细教程(一)--集群概念介绍

    文章导航 集群概念介绍(一) ORACLE集群概念和原理(二) RAC 工作原理和相关组件(三) 缓存融合技术(四) RAC 特殊问题和实战经验(五) ORACLE 11 G版本2 RAC在LINUX ...

  10. Prism 4 文档 ---第10章 Silverlight和WPF之间共享代码

        本主题帮助你理解来自Prism的多目标和它的优缺点.多目标的代码针对两个不同的平台有大致相同的代码库.这允许同时保持代码尽可能多一样能够产生针对两种不同技术的二进制文件.在这种情况下,本节介绍 ...