一什么是串口通信
串口通信是单片机开发必须要掌握的技能,其主要应用场景有很多,比如我们要开发一款自动测温电路板,我们想要可视化查看数据,我们可以将测试得出的温度数据以每秒发送一次的频率发送到上位机上,也就是我们说的PC端,这样我们就可以通过PC的显示屏查看实时温度数据了。又或者我们将单片机与SIM800C等上网模块结合时,我们就可以通过串口通信进行AT指令传输,然后进行实时控制上网模块。
我查看了上海LUAT通信公司旗下的AIR202模块时,发现其也带有串口通信功能,不管是低端的51系列单片机还是高端STM32单片机,都带有串口通信功能,其原理相差无几,掌握了一种串口通信方式再过渡到其他的单片机时也非常简单。
上次我们介绍了串口通信的基本定义与简单概念,大家可以回头再次查看,接下来我们就直接进行串口通信的库函数操作了。
二 硬件交代
我们使用的是STM32F103VET6最小系统板,使用USART1进行串口通信
我们使用CH340进行电平转换并虚拟出串口与PC通信,请提前安装CH340芯片驱动
注意:使用时一定要将TX RX跳线帽插上!!!!!
库函数通信配置步骤:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA,ENABLE);
2 串口复位
复位的目的是当外设出现异常的时候可以通过复位设置,实现该外设的复位,然后重新配置这个外设达到让其重新工作,我们通过USART_DeInit函数进行复位操作,我们来看看这个函数
非常简单的一个函数,只需要写清楚复位哪个USART既可。
USART_DeInit(USART1);
3 GPIO模式配置
我们要使用PA9 PA10进行复用操作,那我们应该如何配置呢?我们来查询一下数据手册
PA9推挽复用输出 PA10浮空输入
关于GPIO如何配置我们在前几篇文章里面已经写得很明白了,大家可以参考以前的文章。
代码:
//USART1_TX PA9 推挽复用输出
GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStrue.GPIO_Pin=GPIO_Pin_9;
GPIO_InitStrue.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStrue);
//USART1_RX PA10 浮空输入
GPIO_InitStrue.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_InitStrue.GPIO_Pin=GPIO_Pin_10;
GPIO_InitStrue.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStrue);
4 串口参数初始化
我们要设置波特率为115200,硬件流控制使能,因为我们通过PC机给单片机发送一个数据,然后单片机接收到数据以后再将此数据返还给PC机,所以我们要将接受发送都使能,我们还要配置为无奇偶校验,无奇偶校验在一定程度上会导致传输的数据不准确,不过对于我们测试来说影响微乎其微。我们要设置停止位字节为1,每次都是8位传输数据。建议大家多看看《STM32库函数手册》有关于USART的函数,在这里我们不再累述。
代码:
USART_InitStrue.USART_BaudRate=115200;
USART_InitStrue.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
USART_InitStrue.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
USART_InitStrue.USART_Parity=USART_Parity_No;
USART_InitStrue.USART_StopBits=USART_StopBits_1,
USART_InitStrue.USART_WordLength=USART_WordLength_8b;
USART_Init(USART1,&USART_InitStrue);
5 开启中断并且初始化NVIC函数
在这里我们使用中断服务函数来写代码,首先NVIC中断通道设置为USART1通道,也就是只有USART1可以开启中断,并且开启中断使能,设置抢占优先级为2,子优先级也为2。我们来看看代码:
NVIC_InitStrue.NVIC_IRQChannel=USART1_IRQn;
NVIC_InitStrue.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=2;
NVIC_InitStrue.NVIC_IRQChannelSubPriority=2;
NVIC_Init(&NVIC_InitStrue);
6 开启串口使能
调用USART_ITConfig函数与USART_Cmd函数并且开启使能为USART1,开启使能
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
USART_Cmd(USART1,ENABLE);
7 写中断执行函数
开启中断以后,我们就要写中断执行函数了,只要中断被处罚,程序便自动执行中断中的函数,程序基本代码为:PC发送给单片机什么数据,单片机便自动返回什么数据
USART1代码
#include "stm32f10x.h"
#include "usart.h"
#include "sys.h"
void MyUSART_Init(void)
{
USART_InitTypeDef USART_InitStrue;
GPIO_InitTypeDef GPIO_InitStrue;
NVIC_InitTypeDef NVIC_InitStrue;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA,ENABLE);
USART_DeInit(USART1);
//USART1_TX PA9
GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStrue.GPIO_Pin=GPIO_Pin_9;
GPIO_InitStrue.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStrue);
//USART1_RX PA10
GPIO_InitStrue.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_InitStrue.GPIO_Pin=GPIO_Pin_10;
GPIO_InitStrue.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStrue);
USART_InitStrue.USART_BaudRate=115200;
USART_InitStrue.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
USART_InitStrue.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
USART_InitStrue.USART_Parity=USART_Parity_No;
USART_InitStrue.USART_StopBits=USART_StopBits_1,
USART_InitStrue.USART_WordLength=USART_WordLength_8b;
USART_Init(USART1,&USART_InitStrue);
NVIC_InitStrue.NVIC_IRQChannel=USART1_IRQn;
NVIC_InitStrue.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=2;
NVIC_InitStrue.NVIC_IRQChannelSubPriority=2;
NVIC_Init(&NVIC_InitStrue);
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
USART_Cmd(USART1,ENABLE);
}
void USART1_IRQHandler(void)
{
u8 Res;
Res=USART_ReceiveData(USART1);
USART_SendData(USART1,Res);
}``
主函数代码:
#include "stm32f10x.h"
#include "usart.h"
#include "delay.h"
void MyUSART_Init(void);
void USART1_IRQHandler(void);
int main(void)
{
MyUSART_Init();
while(1)
{
delay_ms(1000);
USART1_IRQHandler();
}
}