一.通信接口背景知识
1.处理器与外部设备通信的两种方式
1)并行通信
-传物原理: 数据各个位同时传输
优点:速度快
-缺点:占用引脚资源多
2)串行通信
传输原理:数据按位顺序传输
-优点:占用引脚资源少
-缺点:速度相对较慢
2.串行通信
1)按照数据传送方向,分为:
(1)单工:
数据传输只支持数据在一个方向上传输
(2)半双工:
允许数据在两个方向上传输,但是,在某一时刻,只允许数据在一个方向上传输,它实 际上是一种切换方向的单工通信:
(3)全双工:
允许数据同时在两个方向上传输,因此,全双工通信是两个单工通信方式的结合,它要求发送设备和接收设备都有独立的接收和发送能力。
2)串行通信的通信方式
同步通信: 带时钟同步信号传输 SPI,IIC通信接口
异步通信:不带时钟同步信号 -UART(通用异步收发器).单总线
3)常见的串行通信接口
2.STM32串口通信基础
1.STM32的串口通信接口
UART : 通用异步收发器
USART:通用同步异步收发器
STM32F10X,包含3个USART和2个USART
2.UART异步通信方式引脚连接方法:
RXD: 数据输入引脚 , 数据接受。
TXD:数据发送引脚。 数据发送。
3.UART异步通信方式引脚
4.UART异步通信方式特点
-全双工异步通信。
-分数波特率发生器系统,提供精确的波特率。-发送和接受共用的可编程波特率,最高可达4.5Mbits/s
-可编程的数据字长度(8位或者9位):
-可配置的停止位 (支持1或者2位停止位):
-可配置的使用DMA多缓冲器通信
-单独的发送器和接收器使能位
-检测标志:①接受缓冲器 ②发送缓冲器空 ③传输结束标志
-多个带标志的中断源。触发中断。
-其他:校验控制,四个错误检测标志。
3.串口通信过程
4.STM32串口异步通信需要定义的参数
三.串口通信基本原理
1.常用的串口相关寄存器
1)状态寄存器(USART_SR)
其中重点为:
2)数据寄存器(USART_DR)
3)波特比率寄存器(USART_BRR)
波特率计算方法
4)控制寄存器 1(USART_CR1)
2.STM32串口常用库函数
3.串口配置的一般步骤
根据步骤写出代码如下:
#include "stm32f10x.h"
void My_USART1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStrue;
USART_InitTypeDef USART_InitStrue;
NVIC_InitTypeDef NVIC_InitStrue;
//使能时钟GPIOA USART1
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
//初始化IO口GPIO_Pin_9和GPIO_Pin_10
GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP; //推挽复用输出
GPIO_InitStrue.GPIO_Pin=GPIO_Pin_9;
GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&GPIO_InitStrue);
GPIO_InitStrue.GPIO_Mode=GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_InitStrue.GPIO_Pin=GPIO_Pin_10;
GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&GPIO_InitStrue);
//初始化串口的参数
USART_InitStrue.USART_BaudRate =115200; //波特率 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);
//使能串口USART1
USART_Cmd(USART1,ENABLE);
//使能相应中断
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); //接收缓冲区非空
//设置中断的抢占优先级和响应优先级
NVIC_InitStrue.NVIC_IRQChannel=USART1_IRQn;
NVIC_InitStrue.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStrue.NVIC_IRQChannelSubPriority=1;
NVIC_Init(&NVIC_InitStrue);
}
void USART1_IRQHandler(void)
{
u8 res;
if(USART_GetITStatus(USART1,USART_IT_RXNE))
{
res = USART_ReceiveData(USART1); //接收信息
USART_SendData(USART1,res); //发送信息
}
}
int main(void)
{
//设置中断优先级分组
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
//初始化串口
My_USART1_Init();
while(1);
}
代码分析:
①串口时钟使能,GPIO时钟使能:RCC APB2PeriphClockcmd0;
需要使能GPIOA_10和GPIOA_9,需要串行通信Rx和Tx,所以使能USART1
//使能时钟GPIOA USART1
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
②串口复位:USART Delnit(0);这一步不是必须的
③ GPIO端口模式设置:
由上表可知,Tx对应的GPIOA_9配置为推挽复用输出;Rx对应的GPIOA_9配置为浮空输入
GPIO_InitTypeDef GPIO_InitStrue;
//初始化IO口GPIO_Pin_9和GPIO_Pin_10
GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP; //推挽复用输出
GPIO_InitStrue.GPIO_Pin=GPIO_Pin_9;
GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&GPIO_InitStrue);
GPIO_InitStrue.GPIO_Mode=GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_InitStrue.GPIO_Pin=GPIO_Pin_10;
GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&GPIO_InitStrue);
④串口参数初始化并使能:USART_Init0);
根据串口的设置,对串口初始化
//初始化串口的参数
USART_InitStrue.USART_BaudRate =115200; //波特率 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);
//使能串口USART1
USART_Cmd(USART1,ENABLE);
⑥开启中断并且初始化NVIC (如果需要开启中断才需要这个步骤)
NVIC_Init(); USART_ITConfig();
//使能相应中断
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); //接收缓冲区非空
//设置中断的抢占优先级和响应优先级
NVIC_InitStrue.NVIC_IRQChannel=USART1_IRQn;
NVIC_InitStrue.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStrue.NVIC_IRQChannelSubPriority=1;
NVIC_Init(&NVIC_InitStrue);
并在main()函数中对中断优先级分组
//设置中断优先级分组
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
⑦编写中断处理函数:USARTX_IRQHandler()
⑧串口数据收发
void USART_SendData(): //发送数据到串口,DR
uint16 USART_ReceiveData(): //接受数据,从DR读取接受到的数据
⑨串口传输状态获取 USART_GetITStatus(USART1,USART_IT_RXNE)
void USART1_IRQHandler(void)
{
u8 res;
if(USART_GetITStatus(USART1,USART_IT_RXNE))
{
res = USART_ReceiveData(USART1); //接收信息
USART_SendData(USART1,res); //发送信息
}
}
main函数:
int main(void)
{
//设置中断优先级分组
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
//初始化串口
My_USART1_Init();
while(1);
}
5.串口数据传输过程
6.用封装好的usart函数
#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
int main(void)
{
u16 t;
u16 len;
u16 times=0;
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
uart_init(115200); //串口初始化为115200
LED_Init(); //LED端口初始化
KEY_Init(); //初始化与按键连接的硬件接口
while(1)
{
if(USART_RX_STA&0x8000)
{
len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
printf("\r\n您发送的消息为:\r\n\r\n");
for(t=0;t<len;t++)
{
USART_SendData(USART1, USART_RX_BUF[t]);//向串口1发送数据
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
}
printf("\r\n\r\n");//插入换行
USART_RX_STA=0;
}else
{
times++;
if(times%5000==0)
{
printf("\r\n精英STM32开发板 串口实验\r\n");
printf("正点原子@ALIENTEK\r\n\r\n");
}
if(times%200==0)printf("请输入数据,以回车键结束\n");
if(times%30==0)LED0=!LED0;//闪烁LED,提示系统正在运行.
delay_ms(10);
}
}
}
0x8000 = 1000 0000 0000 0000
USART_RX_STA&0x8000 判断最高位是否为1 是否接收成功
if(USART_RX_STA&0x8000)
0x3fff = 0011 1111 1111 1111
USART_RX_STA&0x3fff 得到此次接收到的数据长度
len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度