STM32串口配置流程.docx

上传人:b****6 文档编号:4475602 上传时间:2022-12-01 格式:DOCX 页数:14 大小:302.74KB
下载 相关 举报
STM32串口配置流程.docx_第1页
第1页 / 共14页
STM32串口配置流程.docx_第2页
第2页 / 共14页
STM32串口配置流程.docx_第3页
第3页 / 共14页
STM32串口配置流程.docx_第4页
第4页 / 共14页
STM32串口配置流程.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

STM32串口配置流程.docx

《STM32串口配置流程.docx》由会员分享,可在线阅读,更多相关《STM32串口配置流程.docx(14页珍藏版)》请在冰豆网上搜索。

STM32串口配置流程.docx

STM32串口配置流程

stm32串口通信

  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);  //停止复位

③串口波特率设置

  波特比率寄存器()

  关于波特率设置在函数voiduart_init(u32pclk2,u32bound)里已经设置好,并且封装在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=0010000000001100B

设置成使能串口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.关于波特率的计算

voiduart_init(u32pclk2,u32bound)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

voiduart_init(u32pclk2,u32bound)

voidUSART1_IRQHandler(void)

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

//初始化I/O串口1

//pclk2:

PCLK2时钟频率(Mhz)

//bound:

波特率

voiduart_init(u32pclk2,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&=0XFFFFF00F;//IO状态设置PA9PA10

GPIOA->CRH|=0X000008B0;//IO状态设置

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

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

//波特率设置

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

USART1->CR1|=0X200C;//1位停止无校验位

#ifEN_USART1_RX//如果使能了接收

//使能接收中断

USART1->CR1|=1<<8;//PE中断使能

USART1->CR1|=1<<5;//接收缓冲区非空中断使能

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

#endif

}

//uart.h

#ifndef__USART_H

#define__USART_H

#include"sys.h"

#include"stdio.h"

#defineUSART_REC_LEN200//定义最大接收字节数200

#defineEN_USART1_RX1//使能1禁止0串口1接收

externu8USART_RX_BUF[USART_REC_LEN];//接收缓冲,最大USART_REC_LEN个字节.末字节为换行符

externu16USART_RX_STA;//接收状态标记

voiduart_init(u32pclk2,u32bound);

#endif

#ifEN_USART1_RX//如果使能了接收

//串口1中断服务程序

//注意,读取USARTx->SR能避免莫名其妙的错误

u8USART_RX_BUF[USART_REC_LEN];//接收缓冲,最大USART_REC_LEN个字节.

//接收状态

//bit15,接收完成标志

//bit14,接收到0x0d

//bit13~0,接收到的有效字节数目

u16USART_RX_STA=0;//接收状态标记

voidUSART1_IRQHandler(void)

{

u8res;

#ifdefOS_CRITICAL_METHOD//如果OS_CRITICAL_METHOD定义了,说明使用ucosII了.

OSIntEnter();

#endif

if(USART1->SR&(1<<5))//接收到数据

{

res=USART1->DR;

if((USART_RX_STA&0x8000)==0)//接收未完成

{

if(USART_RX_STA&0x4000)//接收到了0x0d

{

if(res!

=0x0a)USART_RX_STA=0;//接收错误,重新开始

elseUSART_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-1))USART_RX_STA=0;//接收数据错误,重新开始接收

}

}

}

}

#ifdefOS_CRITICAL_METHOD//如果OS_CRITICAL_METHOD定义了,说明使用ucosII了.

OSIntExit();

#endif

}

#endif

#include"sys.h"

#include"usart.h"

#include"delay.h"

#include"led.h"

#include"key.h"

intmain(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&0x8000)//1000000000000000接收成功

{

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

printf("\r\n您发送的消息为:

\r\n");

for(t=0;t

{

USART1->DR=USART_RX_BUF[t];

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

}

printf("\r\n\r\n");//插入换行

USART_RX_STA=0;

}else

{

times++;

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

if(times%30==0)LED0=!

LED0;//闪烁LED,提示系统正在运行.

delay_ms(10);

}

}

}

下面提供一种库函数实现方法

串口通信配置步骤

在上面的介绍中,可能有的朋友很不理解,不过没有关系,下面我们

讲解如何使用库函数对USART进行配置。

这个也是在编写程序中必须要了

解的。

具体步骤如下:

(USART相关库函数在stm32f10x_usart.c和

stm32f10x_usart.h文件中)。

(1)使能串口时钟及GPIO端口时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能GPIOA时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1时钟

(2)GPIO端口模式设置,设置串口对应的引脚为复用功能

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;

(3)初始化串口参数,包含波特率、字长、奇偶校验等参数

voidUSART_Init(USART_TypeDef*USARTx,USART_InitTypeDef*

USART_InitStruct);

typedefstruct

{

uint32_tUSART_BaudRate;//波特率

uint16_tUSART_WordLength;//字长

uint16_tUSART_StopBits;//停止位

uint16_tUSART_Parity;//校验位

uint16_tUSART_Mode;//USART模式

uint16_tUSART_HardwareFlowControl;//硬件流控制

}USART_InitTypeDef;

例如:

USART_InitTypeDefUSART_InitStructure;

USART_InitStructure.USART_BaudRate=9600;//波特率设置

USART_InitStructure.USART_WordLength=USART_WordLength_8b;//字长为8位数据格式

USART_InitStructure.USART_StopBits=USART_StopBits_1;//一个停止位

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,&USART_InitStructure);//初始化串口1

(4)使能串口

voidUSART_Cmd(USART_TypeDef*USARTx,FunctionalStateNewState);

USART_Cmd(USART1,ENABLE);//使能串口1

(5)设置串口中断类型并使能

voidUSART_ITConfig(USART_TypeDef*USARTx,uint16_tUSART_IT,

FunctionalStateNewState);

USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//开启接收中断

USART_ITConfig(USART1,USART_IT_TC,ENABLE);

对应的串口中断类型可在stm32f10x_usart.h中查找到

(6)设置串口中断优先级,使能串口中断通道

NVIC初始化库函数是NVIC_Init()

(7)编写串口中断服务函数

USART1_IRQHandler

ITStatusUSART_GetITStatus(USART_TypeDef*USARTx,uint16_tUSART_IT);

if(USART_GetITStatus(USART1,USART_IT_RXNE)!

=RESET)

{

...//执行USART1接收中断内控制

}

voidUSART_ClearFlag(USART_TypeDef*USARTx,uint16_t

USART_FLAG);

第二个参数为状态标志选项,可选参数可在stm32f10x_usart.h中查找到

例如:

voidUSART1_IRQHandler(void)//串口1中断服务程序

{

u8r;

if(USART_GetITStatus(USART1,USART_IT_RXNE)!

=RESET)//接收中断

{

r=USART_ReceiveData(USART1);//(USART1->DR);//读取接收到的数据

USART_SendData(USART1,r);

while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!

=SET);

}

USART_ClearFlag(USART1,USART_FLAG_TC);

}

/*******************************************************************************

*º¯ÊýÃû:

USART1_Init

*º¯Êý¹¦ÄÜ:

USART1³õʼ»¯º¯Êý

*ÊäÈë:

bound:

²¨ÌØÂÊ

*Êä³ö:

ÎÞ

*******************************************************************************/

voidUSART1_Init(u32bound)

{

//GPIO¶Ë¿ÚÉèÖÃ

GPIO_InitTypeDefGPIO_InitStructure;

USART_InitTypeDefUSART_InitStructure;

NVIC_InitTypeDefNVIC_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);

/*ÅäÖÃGPIOµÄģʽºÍIO¿Ú*/

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//TX//´®¿ÚÊä³öPA9

GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//¸´ÓÃÍÆÍìÊä³ö

GPIO_Init(GPIOA,&GPIO_InitStructure);/*³õʼ»¯´®¿ÚÊäÈëIO*/

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;//RX//´®¿ÚÊäÈëPA10

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;//Ä£ÄâÊäÈë

GPIO_Init(GPIOA,&GPIO_InitStructure);/*³õʼ»¯GPIO*/

//USART1³õʼ»¯ÉèÖÃ

USART_InitStructure.USART_BaudRate=bound;//²¨ÌØÂÊÉèÖÃ

USART_InitStructure.USART_WordLength=USART_WordLength_8b;//×Ö³¤Îª8λÊý¾Ý¸ñʽ

USART_InitStructure.USART_StopBits=USART_StopBits_1;//Ò»¸öֹͣλ

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,&USART_InitStructure);//³õʼ»¯´®¿Ú1

USART_Cmd(USART1,ENABLE);//ʹÄÜ´®¿Ú1

USART_ClearFlag(USART1,USART_FLAG_TC);

USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//¿ªÆôÏà¹ØÖжÏ

//Usart1NVICÅäÖÃ

NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;//´®¿Ú1ÖжÏͨµÀ

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//ÇÀÕ¼ÓÅÏȼ¶3

NVIC_InitStructure.NVIC_IRQChannelSubPriority=3;//×ÓÓÅÏȼ¶3

NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//IRQͨµÀʹÄÜ

NVIC_Init(&NVIC_InitStructure);//¸ù¾ÝÖ¸¶¨µÄ²ÎÊý³õʼ»¯VIC¼Ä´æÆ÷¡¢

}

/*******************************************************************************

*º¯ÊýÃû:

USART1_IRQHandler

*º¯Êý¹¦ÄÜ:

USART1ÖжϺ¯Êý

*ÊäÈë:

ÎÞ

*Êä³ö:

ÎÞ

*******************************************************************************/

voidUSART1_IRQHandler(void)//´®¿Ú1ÖжϷþÎñ³ÌÐò

{

u8r;

if(USART_GetITStatus(USART1,USART_IT_RXN

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 考试认证 > 从业资格考试

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1