STM32串口通讯程序

更新时间:2025-12-10 21:27:02 阅读: 评论:0


2022年7月13日发
(作者:美国探亲签证)

通过学习USART1深入STM32F107VCT6的串口通信

(2012-05-0513:27:28)

转载▼

标签:分类:STM32

波特率

串口

引脚

函数

杂谈

STM32有数个串口,每个串口都有一个自己独立的波特率寄存器

USART_BRR,通过设置该寄存器就可以达到配置不同波特率的目的,由

于STM32采用分数波特率,所以STM32的串口波特率设置范围很宽,而

且误差很小。

在STM32的参考手册中,串口被描述成通用同步异步收发

器(USART),它提供了一种灵活的方法与使用工业标准RZ异步串行数

据格式的外部设备之间进行全双工数据交换。USART利用分数波特率发

生器提供宽范围的波特率选择。它支持同步单向通信和半双工单线通

信,也支持LI(局部互联网),智能卡协议和IrDA(红外数据组织)

SIREDEC规范,以及调制解调器(CTS/RTS)操作。它还允许多处理器通

信。还可以使用DMA方式,实现高速数据通信。

USART通过3个引脚与其他设备连接在一起,任何USART双向通信至少

需要2个引脚:接受数据输入(RX)和发送数据输出(TX)。

RX:接受数据串行输入。通过过采样技术来区别数据和噪音,从而恢复

数据。

TX:发送数据输出。当发送器被禁止时,输出引脚恢复到它的I/O端口

配置。当发送器被激活,并且不发送数据时,TX引脚处处于高电平。在

单线和智能卡模式里,此I/O口被同时用于数据的发送和接收。

一般有两种工作方式:查询和中断。

(1)查询:串口程序不断地循环查询,看看当前有没有数据要它传送。

如果有,就帮助传送(可以从PC到STM32板子,也可以从STM32板子

到PC)。

(2)中断:平时串口只要打开中断即可。如果发现有一个中断来,则

意味着要它帮助传输数据——它就马上进行数据的传送。同样,可以从

PC到STM3板子,也可以从STM32板子到PC

注意:

发动和接受都需要配合标志等待。

只能对一个字节操作,对字符串等大量数据操作需要写函数

使用串口所需设置:RCC初始化里面打开RCC_APB2PeriphClockCmd

(RCC_APB2Periph_USARTx);GPIO里面管脚设定:串口RX(50Hz,

I_FLOATIG);串口TX(50Hz,AF_PP);

printf函数重定义(不必理解,调试通过以备后用)

需要c标准函数:#include"stdio.h"

增加为putchar函数。

intputchar(intc)//putchar函数

{if(c=='n'){putchar('r');}//将printf的n变成r

USART_SendData(USART1,c);//发送字符

while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET){}

//等待发送结束

returnc;//返回值

}

printf使用变量输出:%c字符,%d整数,%f浮点数,%s字符串,/n或

/r为换行。注意:只能用于main.c中。

另外:

STM32支持三个串口,在usart1默认引脚被占用的情况下可以将usart1

映射到PB0.6和PB0.7上。实现的方法如下:

1、打开GPIO的AFIO时钟,使用stm32功能模块之前,必须开时钟;

2、使能USART1的映射,

3、配置USART1映射后的GPIO(PB0.6,PB0.7)

具体实现:

1、在set_systm函数中添加如下模块,打开AFIO时钟,使能USART1

映射

#ifdefUSB_TO_KLIE_USART1_REMAP

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,EABLE);

GPIO_PinRemapConfig(GPIO_Remap_USART1,EABLE);

#endif

2、在set_systm函数中添加如下模块,配置USART1映射后的GPIO

#ifdefUSB_TO_KLIE_USART1_REMAP

GPIO__Pin=GPIO_Pin_7;

GPIO__Mode=GPIO_Mode_I_FLOATIG;

GPIO_Init(GPIOB,&GPIO_InitStructure);

GPIO__Pin=GPIO_Pin_6;

GPIO__Speed=GPIO_Speed_50MHz;

GPIO__Mode=GPIO_Mode_AF_PP;

GPIO_Init(GPIOB,&GPIO_InitStructure);

#else

GPIO__Pin=GPIO_Pin_10;

GPIO__Mode=GPIO_Mode_I_FLOATIG;

GPIO_Init(GPIOA,&GPIO_InitStructure);

GPIO__Pin=GPIO_Pin_9;

GPIO__Speed=GPIO_Speed_50MHz;

GPIO__Mode=GPIO_Mode_AF_PP;

GPIO_Init(GPIOA,&GPIO_InitStructure);

#endif

例:

#include"stm32f10x.h"

#include"stm32_eval.h"

#include

USART_InitTypeDefUSART_InitStructure;//定义结构体类型变量

voidGPIO_Configuration(void);//声明GPIO配置函数

#ifdef__GUC__

#definePUTCHAR_PROTOTYPEint__io_putchar(intch)//此处

定义为putchar应用

#else

#definePUTCHAR_PROTOTYPEintfputc(intch,FILE*f)

#endif

intmain(void)

{

SystemInit();//配置系统

时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|

RCC_APB2Periph_AFIO,EABLE);//打开APB2功能时钟(UART1为连

接在APB2上的高速外设)开启了串口时钟和复用功能时钟

GPIO_Configuration();//调用GPIO配置

函数

USART__BaudRate=

115200;//设置USART传输波特率

USART__WordLength=

USART_WordLength_8b;//设置USART传输数据位一帧为8位

USART__StopBits=

USART_StopBits_1;//设置USART传输每帧一个停止位

USART__Parity=

USART_Parity_o;//设置USART无奇偶校验

USART__HardwareFlowControl=

USART_HardwareFlowControl_one;//设置USART无硬件流控制

USART__Mode=USART_Mode_Rx|

USART_Mode_Tx;//开启USART发送和接受功能

USART_Init(USART1,

&USART_InitStructure);//初始

化USART1设置

USART_Cmd(USART1,EABLE);//开启USART1

printf("nr李继超是个好人吗?nr");

printf("nr回答:李继超是个大好

人!nr");

printf("nr菏泽是个是个美丽的地方!nr");

printf("nr发生了什么?你是猴子请来的救兵

吗?nr");

printf("nr嗯!李继超的确是个大好人!!!你才魔道呢!

哼!!!nr");//配置输出数据

while(1)

{

}

}

voidGPIO_Configuration(void)

{

GPIO_InitTypeDefGPIO_InitStructure;//定义结构体变量类

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,EABLE);//

打开GPIOA的功能时钟

GPIO__Pin=GPIO_Pin_9;//选择

GPIO引脚GPIO_Pin_9

GPIO__Speed=GPIO_Speed_50MHz;//设

置GPIO速率

GPIO__Mode=GPIO_Mode_AF_PP;//设置

GPIO_pin_9为复用功能推挽输出

GPIO_Init(GPIOA,&GPIO_InitStructure);//初始化

GPIO_Pin_9设置

GPIO__Pin=GPIO_Pin_10;//选择GPIO

引脚GPIO_Pin_10

GPIO__Mode=

GPIO_Mode_I_FLOATIG;//设置GPIO_Pin_10浮空输入

GPIO_Init(GPIOA,&GPIO_InitStructure);//初始化

GPIO_Pin_10设置

}

PUTCHAR_PROTOTYPE//重定义printf函数

{

USART_SendData(USART1,(uint8_t)

ch);//发送字符串

while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==

RESET)//检测是否发送完成

{}

returnch;

}

#ifdefUSE_FULL_ASSERT

voidassert_failed(uint8_t*file,uint32_tline)

{

while(1)

{}

}

#endif

将AVR上的队列串口驱动程序修改后,运行在STM32开发板,采用中断方式

接收和中断发送,并加入了缓冲收发队列操作。由于该驱动是用来操作西门子的

TC35或MC55等通信模块,所以加入了“等待串口接收完成”函数,该函数需要

一个10ms的定时进行计数累加。

#defineSMS_UART0_c

/*

****************************************************************************************

*********************

*

*STM32UART1driver

*

*File:UART0.c

*By:hjjft

****************************************************************************************

*********************

*/

/////////////////////////////////////////////////

//这里将串口1写作0,主要原因是AVR是串口0,为了方便移植,这

里仍然称为串口0//

/////////////////////////////////////////////////

staticcharUART0_RxBuf[UART0_RX_BUFFER_SIZE];

staticvolatileunsignedcharUART0_RxHead;//

staticvolatileunsignedcharUART0_RxTail;

staticcharUART0_TxBuf[UART0_TX_BUFFER_SIZE];//

staticvolatileunsignedcharUART0_TxHead;

staticvolatileunsignedcharUART0_TxTail;

//------------------------------------------------------------

staticvolatileunsignedcharFrame_counting;

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

*Functioname:VIC_Configuration

*Description:ConfiguresVectorTablebaselocation.

*Input:one

*Output:one

*Return:one

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

voidVIC_USART_Configuration(void)

{

VIC_InitTypeDefVIC_InitStructure;

/*EnabletheUSART1Interrupt*/

VIC__IRQChannel=USART1_IRQChannel;//

VIC__IRQChannelPreemptionPriority=1;

VIC__IRQChannelSubPriority=10;

//VIC__IRQChannelCmd=EABLE;

VIC_Init(&VIC_InitStructure);

}

voidGPIO_USART_Configuration(void)

{

GPIO_InitTypeDefGPIO_InitStructure;

/*ConfigureUSART1Tx(PA.09)asalternatefunctionpush-pull*/

GPIO__Pin=GPIO_Pin_9;

GPIO__Mode=GPIO_Mode_AF_PP;

GPIO__Speed=GPIO_Speed_50MHz;

GPIO_Init(GPIOA,&GPIO_InitStructure);

/*ConfigureUSART1Rx(PA.10)asinputfloating*/

GPIO__Pin=GPIO_Pin_10;

GPIO__Mode=GPIO_Mode_I_FLOATIG;

GPIO_Init(GPIOA,&GPIO_InitStructure);

}

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

*Functioname:USART_Configuration

*Description:ConfigurestheUSART1.

*Input:one

*Output:one

*Return:one

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

voidUSART_Configuration(unsignedlongbaudrate)

{

USART_InitTypeDefUSART_InitStructure;

USART_ClockInitTypeDefUSART_ClockInitqlt;

/*USART1configuration------------------------------------------------------*/

/*USART1configuredasfollow:

-BaudRate=115200baud

-WordLength=8Bits

-OneStopBit

-oparity

-Hardwareflowcontroldisabled(RTSandCTSsignals)

-Receiveandtransmitenabled

-USARTClockdisabled

-USARTCPOL:Clockisactivelow

-USARTCPHA:Dataiscapturedonthemiddle

-USARTLastBit:Theclockpulseofthelastdatabitisnotoutput

to

theSCLKpin

*/

USART__BaudRate=baudrate;

USART__WordLength=USART_WordLength_8b;

USART__StopBits=USART_StopBits_1;

USART__Parity=USART_Parity_o;

USART__HardwareFlowControl=USART_HardwareF

lowControl_one;

USART__Mode=USART_Mode_Rx|USART_Mode

_Tx;//

USART_Init(USART1,&USART_InitStructure);

USART__Clock=USART_Clock_Disable;

USART__CPOL=USART_CPOL_Low;//USART_Cl

_CPHA=USART_CPHA_2Edge;//USART_ClockInitqlt.

USART_LastBit=USART_LastBit_Disable;//

USART_ClockInit(USART1,&USART_ClockInitqlt);

USART_ITConfig(USART1,USART_IT_RXE,EABLE);

USART_Cmd(USART1,EABLE);//

}

//串口初始化

voidUART0_InitUART(unsignedlongbaudrate)

{

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Peri

ph_GPIOA,EABLE);

VIC_USART_Configuration();

GPIO_USART_Configuration();

USART_Configuration(baudrate);

UART0_RxTail=0;

UART0_RxHead=0;

UART0_TxTail=0;

UART0_TxHead=0;

}

//--------------------------------------------------

voidSIGAL_Usart0_RX(void)//接收中断

{

u8data;

u8tmphead;

data=USART_ReceiveData(USART1);//

Frame_counting=0;

tmphead=(UART0_RxHead+1)&UART0_RX_BUFFER_MAS

K;//UART0_RxHead=tmphead;//

if(tmphead==UART0_RxTail)

{

//这里加入队列溢出保护

}

UART0_RxBuf[tmphead]=data;

}

//--------------------------------------------------

voidSIGAL_Usart0_TX(void)//发送中断

{

u8tmptail;

if(UART0_TxHead!=UART0_TxTail)

{

tmptail=(UART0_TxTail+1)&UART0_TX_BUFFER_MAS

K;UART0_TxTail=tmptail;

USART_SendData(USART1,UART0_TxBuf[tmptail]);

}

else

{

USART_ITConfig(USART1,USART_IT_TXE,DISABLE);//

}

}

//从接收队列读取一个字符

unsignedcharUART0_ReceiveByte(void)

{

unsignedchartmptail;

while(UART0_RxHead==UART0_RxTail);//

tmptail=(UART0_RxTail+1)&UART0_RX_BUFFER_MASK;

UART0_RxTail=tmptail;

returnUART0_RxBuf[tmptail];

}

//将一个字节放入发送队列

voidUART0_TransmitByte(chardata)

{

unsignedchartmphead;

tmphead=(UART0_TxHead+1)&UART0_TX_BUFFER_MASK;

while(tmphead==UART0_TxTail);

UART0_TxBuf[tmphead]=data;

UART0_TxHead=tmphead;

USART_ITConfig(USART1,USART_IT_TXE,EABLE);//

}

//发送一个字符串

voidUART0_Transmitstr(char*str)//

{

//unsignedinti="0";

while(*str)

{

UART0_TransmitByte(*str++);

}

}

//清空接收缓冲区

voidUART0_ClearspatialReceiveBuffer(void)

{

unsignedcharx;

x=0;

UART0_RxTail=x;

UART0_RxHead=x;

}

//等待接收完成

voidUART0_RXED(void)

{

//UART0_Transmitstr("wite_start-");

unsignedintx="0";

while((!UART0_DataInReceiveBuffer())&(x<100))//

{

x++;

DelayMs(10);//10ms

}

x=0;

while((Frame_counting<2)&&(x<1000))//?D??êy?Y?óê?íê3é,×??à1sí?3?

{

x++;

DelayMs(1);//1ms

}

}

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

*Functioname:USART1_IRQHandler

*Description:ThisfunctionhandlesUSART1globalinterruptrequest.

*Input:one

*Output:one

*Return:one

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

voidUSART1_IRQHandler(void)

{

if(USART_GetITStatus(USART1,USART_IT_RXE)==SET)

{

USART_ClearITPendingBit(USART1,USART_IT_RXE);//

SIGAL_Usart0_RX();

}

if(USART_GetITStatus(USART1,USART_IT_TXE)==SET)

{

USART_ClearITPendingBit(USART1,USART_IT_TXE);//

SIGAL_Usart0_TX();

}

}


本文发布于:2022-07-13 21:44:25,感谢您对本站的认可!

本文链接:http://www.wtabcd.cn/falv/fa/82/9755.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 站长QQ:55-9-10-26