stm32串口

这里我们关注一下两个位,第5、6位RXNE和TC。

RXNE(读数据寄存器非空),当该位被置1的时候,就是提示已经有数据被接收到了,而且能够读出来了。这时候我们要做的就是尽快去读取USART_DR。通过读USART_DR能够将该位清零。也能够向该位写0。直接清除。

TC(发送完毕),当该位被职位的时候。表示USART_DR内的数据已经被发送完毕了。

假设设置了这个位的中断,则会产生中断。该位也有两种清零方式:1)读USART_SR,写USART_DR。

2)直接向该位写0。

//初始化IO 串口1

//pclk2 CLK2时钟频率(Mhz)

//bound:波特率

void uart_init(u32 pclk2。u32bound)

{

floattemp;

u16mantissa;

u16fraction;

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=0X444444B4;//IO状态设置

RCC->APB2RSTR|=1<<14;

//复位串口1

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

//波特率设置

USART1->BRR=mantissa; // 波特率设置

USART1->CR1|=0X200C;

//1位停止,无校验位.

#ifdef EN_USART1_RX

//假设使能了接收

//使能接收中断

USART1->CR1|=1<<8;

//PE中断使能

USART1->CR1|=1<<5;

//接收缓冲区非空中断使能

MY_NVIC_Init(3。3。USART1_IRQChannel,2);//组2。最低优先级

#endif

}

从该代码能够看出,其初始化串口的过程,和我们前面介绍的一致先计算得到USART1->BRR的内容。

然后開始初始化串口引脚。接着把USART1复位,然之后设置波特率和奇偶校验等。

这里须要注意一点,由于我们使用到了串口的中断接收,必须在usart.h里面定义 EN_USART1_RX 。该函数才会配置中断使能。以及开启串口1的NVIC中断。这里我们把串口1中断放在组2,优先级设置为组2里面的最低。

再介绍一下串口1的中断服务函数USART1_IRQHandler,该函数的名字不能自定义了,MDK已经给每一个中断都分配了一个固定的函数名,我们直接用就能够了。

详细这些函数的名字是什么,我们能够在MDK提供的样例里面,找到stm32f10x_it.c,该文件中面包括了STM32全部的中断服务函数。USART1_IRQHandler的代码例如以下:

void USART1_IRQHandler(void)

{

u8res;

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;//接收错误。又一次開始

elseUSART_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;//接收数据错误,又一次開始接收

}}}}}

该函数的重点就是推断接收是否完毕,通过检測是否收到0X0D、0X0A的连续2个字节(回车键)来检測是否结束。当检測到这个结束序列之后。就会置位USART_RX_STA的最高为来标记已经收到了一次数据。之后等待外部函数清空该位之后才開始第二次接收。所接收的数据所有存放在USART_RX_BUF里面,一次接收数据不能超过64个字节。否则被丢弃。

介绍完了这两个函数。我们回到test.c,在test.c里面编写例如以下代码:

#include

#include "sys.h"

#include "usart.h"

#include "delay.h"

#include "led.h"

#include "key.h"

//Mini STM32开发板范例代码3

//串口实验

//正点原子@ALIENTEK

//2010.5.28

int main(void)

{

u8t;

u8len;

u16times=0;

Stm32_Clock_Init(9);//系统时钟设置

delay_init(72);

//延时初始化

uart_init(72。9600);

//串口初始化为9600

LED_Init();

//初始化与LED连接的硬件接口

while(1)

{

if(USART_RX_STA&0x80)

{len=USART_RX_STA&0x3f;//得到此次接收到的数据长度

printf("n您发送的消息为:n");

for(t=0;t

{USART1->DR=USART_RX_BUF[t];

while((USART1->SR&0X40)==0);//等待发送结束}

printf("nn");//插入换行

USART_RX_STA=0;

}else

{times++;

if(timesP00==0)

{printf("nMiniSTM32开发板

串口实验n");

printf("正点原子@ALIENTEKnnn");

}

if(times 0==0)printf("请输入数据,以回车键结束n");

if(times0==0)LED0=!LED0;//闪烁LED,提示系统正在执行.

delay_ms(10);}}}

这段代码比較简单,重点看下下面两句:

USART1->DR=USART_RX_BUF[t];

while((USART1->SR&0X40)==0);//等待发送结束

第一句。事实上就是发送一个字节到串口。通过直接操作寄存器来实现的。第二句呢,就是我们在写了一个字节在USART1->DR之后,要检測这个数据是否已经被发送完毕了,通过检測USART1->SR的第6位,是否为1来决定能否够開始第二个字节的发送。

寄存器:

1.串口1的时钟使能在APB2ENR寄存器第14位(其它串口的时钟使能位都在APB1ENR)。

2.串口1的复位是通过配置APB2RSTR寄存器的第14位(其它串口的复位位在APB1RSTR里面)

3.波特率寄存器USART_BRR(低16位有效)

4.控制寄存器USART_CR1~3:低14位有效;位13(UE)是串口使能位,位3(TE)是发送使能位,位2(RE)是接受使能位

5.数据寄存器USART_DR(低9位有效,兼具读写功能)

6.状态寄存器USART_SR:5位RXNE(读数据寄存器非空)。6位TC(发送完毕)

Copyright © 2022 历届世界杯_世界杯篮球 - cnfznx.com All Rights Reserved.