本文介绍STM8L051F3的USART(串口)部分相关知识。内容分为以下几部分:
- USART简介
- printf与getchar函数实现
1、USART简介USART(Universal synchronous/asynchronous receiver transmitter ),中文翻译过来就是通用同步/异步收发器,功能强大,支持同步单向通信和半双工通讯、智能卡协议和IrDA(红外数据组织)解码规范,同时也支持多路处理器通讯,使用多路缓存配置的DMA还能实现高速数据通讯。主要性能如下:
- 全双工异步通讯
- NRZ标准格式
- 高精度波特率系统生成器
- 可编程数据字长度(8/9位)
- 可配置停止位-1/2位
- 同步通讯发送器的时钟输出
- 单线半双工通讯
- IrDA SIR编码器 解码器
- 智能卡仿真能力
- 智能卡接口支持在ISO 7816-3标准定义的智能卡的异步协议
- 智能卡运行的5位停止位
- 配置多路缓冲通信可以使用DMA
- 可指定使能发送器和接收器
- 转移器检测标志位
- 奇偶检验控制
- 4个错误检测标志
- 8个中断源和标志位
- 发送数据寄存器空
- 发送完成
- 接收数据寄存器满
- 空闲接收
- 就检验错误
- 数据溢出错误
- 结构错误
- 噪声错误
- 两个中断向量
- 降低功耗模式
- 多处理器通讯---如果没有发生地址匹配进入静音模式(mute mode)
- 静音模式下唤醒(在空闲总线上检测到地址匹配)
- 2个接收唤醒模式:
USART在进行双向通讯时最少需要两个引脚:USART_RX串行数据输入引脚与USART_TX串行数据输出引脚,它们在正常的USART模式下的数据收发有一个固定的格式:
- 在发送或接收前,总线要空闲
- 一个起始位
- 一个数据字(8位或9位),最低位先发送
- 1、1.5或2个停止位表示一帧数据传输完毕
- 一个状态寄存器(USART_SR)
- 数据寄存器(USART_DR)
- 16位波特率预分频器(USART_BRR)
- 用于智能卡模式的Guard time寄存器
注:我们经常使用的串口起始是指UART(通用异步收发器),UART与USART的根本区别就是USART可以同步进行收发,USART比UART多一个CLK引脚。
USART模块的框图如下
2、printf与getchar函数实现2.1 USART1配置本小节介绍如何使用USART1来重定向C语言库的printf与getchar函数,通过串口向上位机(串口助手)打印数据以及从上位机获取数据。使用的例程:STM8L051F3_08_UART。USART1配置:
1)复位USART1(将USART1相关寄存器恢复为缺省值)
2)使能USART1外设时钟
3)映射USART1相关IO口:TX-->PA2、RX-->PA3
4)配置TX&RX的IO口:RX上拉输入、TX推挽输出、使能两者的外部上拉电阻
5)USART1初始化:波特率9600、数据位8位、停止位1位、无奇偶校验、使能发送&接收模式
注:该波特率是在系统时钟为16M的情况下
2.2 例程介绍重定向C语言库首先要包含stdio.h头文件,然后还需要在main.c文件下添加相关的数据类型定义:
#ifdef _RAISONANCE_
#define PUTCHAR_PROTOTYPE int putchar (char c)
#define GETCHAR_PROTOTYPE int getchar (void)
#elif defined (_COSMIC_)
#define PUTCHAR_PROTOTYPE char putchar (char c)
#define GETCHAR_PROTOTYPE char getchar (void)
#else /* _IAR_ */
#define PUTCHAR_PROTOTYPE int putchar (int c)
#define GETCHAR_PROTOTYPE int getchar (void)
#endif /* _RAISONANCE_ */
在main.c文件下重写printf与getchar相关的函数:
PUTCHAR_PROTOTYPE
{
/* Write a character to the USART */ USART_SendData8(USART1, c); /* Loop until the end of transmission */ while(USART_GetFlagStatus(USART1, USART_FLAG_TC)== RESET); return(c); }
GETCHAR_PROTOTYPE
{
int c = 0; /* Loop until the Read data register flag is SET */ while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE)== RESET); c = USART_ReceiveData8(USART1); return(c); }
printf与getchar相关的函数使用USART1,USART1的初始化实现在uart1.c文件下:
void UART1_Init(void)
{
USART_DeInit(USART1); //将USART1的各个寄存器值恢复为缺省值 /* 使能USART1时钟外设 */ CLK_PeripheralClockConfig(CLK_Peripheral_USART1, ENABLE); /* 映射UART1的IO口:TX-->PA2 RX-->PA3 */ SYSCFG_REMAPPinConfig(REMAP_Pin_USART1TxRxPortA, ENABLE); /* 配置UART1的RX&TX的IO口 */ GPIO_Init(UART1_RX_PORT, UART1_RX_PINS, GPIO_Mode_In_PU_No_IT); GPIO_Init(UART1_TX_PORT, UART1_TX_PINS, GPIO_Mode_Out_PP_High_Slow); GPIO_ExternalPullUpConfig(UART1_RX_PORT, UART1_RX_PINS, ENABLE); GPIO_ExternalPullUpConfig(UART1_TX_PORT, UART1_TX_PINS, ENABLE); /* UART1初始化 */ USART_Init(USART1, (uint32_t)9600, //波特率9600 USART_WordLength_8b, //数据宽度8位 USART_StopBits_1, //一位停止位 USART_Parity_No, //无奇偶校验 (USART_Mode_TypeDef)(USART_Mode_Tx | USART_Mode_Rx));//发送&接收模式 }
UART1_RX&UART1_TX默认是PC2&PC3,但是STM8L051F3没有这两个引脚,所以需要把UART1_RX&UART1_TX映射到PA3&PA2(也可以映射到PC6&PC5,不过这两个引脚已经连接了外部晶振),UART1_RX&UART1_TX的IO口在uart1.h中定义:
/* 宏定义 --------------------------------------------------------------------*/
/* 定义UART1 IO PORT与PIN */
#define UART1_RX_PORT (GPIOA)
#define UART1_RX_PINS (GPIO_Pin_3)
#define UART1_TX_PORT (GPIOA)
#define UART1_TX_PINS (GPIO_Pin_2)
最后在主函数中利用printf函数打印信息,然后在循环中等待输入(并将输入的信息打印出来),如下:
void main(void)
{
char ans; /* 配置系统时钟频率为16MHz */ CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_1); UART1_Init(); //UART1初始化 /* 打印字符 */ printf("\n\rUART1的测试例程,重定向C语言库printf&scanf函数\n\r"); printf("Enter Text\n\r"); while(1) { /* 等待输入字符 */ ans = getchar(); /* 打印输入的字符 */ printf("%c", ans); } }
使用ST-LINK把程序下载到开发板,此例程需要使用一个USB转TTL模块将开发板与电脑PC连接起来(TXD-->PA3、RXD-->PA2、GND-->GND),然后在电脑上位机(串口调试助手)设置波特率9600,数据位8,停止位1,无奇偶校验,打开电脑识别的COM口,然后复位开发板就可以看到打印信息(通过上位机向开发板发送数据,数据也会重新打印在上位机上):
|