小白学STM32---串行通信原理

一.通信接口背景知识

1.处理器与外部设备通信的两种方式

        1)并行通信
        -传物原理: 数据各个位同时传输
        优点:速度快
        -缺点:占用引脚资源多
        2)串行通信
        传输原理:数据按位顺序传输
        -优点:占用引脚资源少
        -缺点:速度相对较慢

2.串行通信

 1)按照数据传送方向,分为:
   (1)单工:     

      数据传输只支持数据在一个方向上传输

   (2)半双工

       允许数据在两个方向上传输,但是,在某一时刻,只允许数据在一个方向上传输,它实 际上是一种切换方向的单工通信:

   (3)全双工:
        允许数据同时在两个方向上传输,因此,全双工通信是两个单工通信方式的结合,它要求发送设备和接收设备都有独立的接收和发送能力。

 

2)串行通信的通信方式
        同步通信:   带时钟同步信号传输    SPI,IIC通信接口
        异步通信:不带时钟同步信号     -UART(通用异步收发器).单总线

3)常见的串行通信接口

 2.STM32串口通信基础

1.STM32的串口通信接口

        UART : 通用异步收发器

        USART:通用同步异步收发器

        STM32F10X,包含3个USART2个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;//得到此次接收到的数据长度

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值