本文介绍串口通信最基本也是最常用的用法,全双工、异步通讯方式。它只需要3根线连接即可,发送(TX)、接收(RX)及地(GND)。
配置串口通信,至少要设置以下几个参数:字长(一次传送的数据长度)、波特率(每秒传输的数据位数)、奇偶校验位、还有停止位。
对于STM32可有多达5个串口(3个通用同步异步收发器USART和2个通用异步收发器UART),从驱动库中也可以发现:
#define RCC_APB2Periph_USART1 ((uint32_t)0x00004000)
#define RCC_APB1Periph_USART2 ((uint32_t)0x00020000)
#define RCC_APB1Periph_USART3 ((uint32_t)0x00040000)
#define RCC_APB1Periph_UART4 ((uint32_t)0x00080000)
#define RCC_APB1Periph_UART5 ((uint32_t)0x00100000)
下面以最常用到的USART1为倒来说明,其发送端(TX)默认的为管脚PA9,接收端(RX)默认为PA10,利用库函数其初始化代码为:
/
**
* @brief 初始化IO 串口1
* @param bound:波特率
* @retval None
*/
void USART1_Debug_Init(u32 bound)
{
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
assert_param(bound > 0);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟
USART_DeInit(USART1); //复位串口1
//USART1_TX PA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA9
//USART 初始化设置
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_Tx; //发送模式
USART_Init(USART1, &USART_InitStructure); //初始化串口
USART_Cmd(USART1, ENABLE); //使能串口
}
至此就可以进行发送了,需要调用USART_SendData函数。比如要发送"Hello"
则要进行如下调用:
USART_SendData(USART1, 'H');
USART_SendData(USART1, 'e');
USART_SendData(USART1, 'l');
USART_SendData(USART1, 'l');
USART_SendData(USART1, 'o');
USART_SendData(USART1, '\n');
是不是感觉到很麻烦,能否像通用C语言中那样调用printf函数直接打印输出呢?
答案是肯定的,只需要进行简单的重定向就可以搞定,为了实现重定向printf()函数,我们需要重写 fputc() 这个c标准库函数,
因为printf()在 c标准库函数中实质是一个宏,最终是调用了 fputc()这个函数的。
/
**
* @brief 重定义fputc函数
* @param int ch 要发送数据 , FILE *f 指向特定文件指针
* @retval int ch
*/
int fputc(int ch, FILE *f)
{
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
{
}
USART_SendData(USART1, (u8)ch);
return ch;
}
另外要注意的是,需要在MDK下加选中如下图选项:
图。
至此就可以轻松的向世界问好了,只需一句
printf("Hello World \n");
但有一点要注意的,利用这种技巧打印消息时会使嵌入式软件效率变低,我曾在调试软件时加入窗口看门狗,但系统总是莫名的复位,最后调试才发现是因主轮循中调用printf导致延时喂狗了。