当前位置: 首页 > news >正文

串口USART

1 常见的通信方式

1.1串行通信和并行通信

串行通信:速度教并行慢,但是占用的硬件资源少,通常只需要时钟线,一两根数据线还
有片选线即可。
并行通信:速度快,但是需要很多根数据线、地址线等。

1.2全双工,半双工和单工通信

全双工:同一时刻双方可以互相发送数据、接收数据
半双工:同一时刻只能有一方可以给另外一方发送数据,即此发彼收,此收彼发
单工:只能由发送方数据发送给接收方

1.3.同步通信和异步通信

同步通信和异步通信都是针对串行通信而言
异步通信
      1.数据是以字符为单位组成字符帧传输的。
      2.字符帧由发送端一帧一帧的发送,每帧数据均是低位在前,高位在后,通过传输线被接收端        一帧一帧的接收。
      3.发送端和接收端可以有各自独立的时钟来控制数据的发送和接收,这两个时钟各自独立,互        不同步。
      4. 接收端依靠字符帧格式来判断发送端是何时开始和结束发送的。
      5. 字符帧也叫做数据帧,由起始位,数据位,奇偶校验位,停止位等部分组成,是异步通信的        一个重要指标。
      6. 同步通信的另一个重要指标是波特率。
同步通信
      1. 同步是指在约定的通信速率下,发送端和接收端的时钟信号和相位始终保持一致,保证通信          双方在发送和接收数据时具有完全一致的定时关系。
      2. 同步通信把许多字符组成一个信息帧,每帧的开始用同步字符来表示。
      3. 在绝大多数场合下,发送端和接收端,采用的都是同一个时钟,所以在传送数据的同时还要          发送时钟信号,以便接收端可以使用时钟信号来确定每一个信息位。
      4. 同步通信一次通信只能传送一帧信息。

1.4.通信速率

对于同步通信,通信速率由时钟信号决定,时钟信号越快,传输速度越快。
对于异步通信来说,需要收发双方提前统一通信速率,这也就是我们串口调试时,波特率不对显示乱码的原因。
                                                                        
1.4.1比特率:系统在单位时间内传输的比特率(二进制0或1)个数,通常用Rb 表示,单位是比特(bit/s ),缩写为 bps
1.4.2. 波特率:系统在单位时间内传输的码元个数,通常用 RB 来表示,单位是波特( Bd
1.4.3. 码元有 N 个状态时,比特率与波特率的关系式: RB=Rb x log2N

1.5.常见的通信协议

在嵌入式中,有众多的通信协议,往往从性能,成本,稳定性,易用性等角度考虑选择合
适的协议。

2 串口基础知识

2.1.电平特性

常见通信接口标准:

2.2串口传输协议

串口设备连接示意图:
参数概念:
波特率:一般选波特率都会有 9600 19200 115200 等选项,其实意思就是每秒传输这么多个比特数(bit )。
起始位:先发出一个逻辑 ‘0’ 的信号,表示传输数据的开始。
数据位:可以是 5~8 位逻辑 “0” “1”, 先传输 Bit0 ,再传输 bit1 ,以此类推。
校验位:数据位加上这一位之后,使得 “1” 的位数应为偶数(偶校验)或者奇数(奇校验),以此来校验数据传送的正确性,校验位是可选的,可以不传输。
停止位:它是一个字符数据的结束标志,数据线变回逻辑 “1”

2.3STM32F103USART资源

1. STM32103 有三个通用同步异步收发器 USART ,两个通用异步收发器 UART USART也可以当作UART 使用。
2. 通常使用的是 UART 功能, USART 在某些场合会使用到,选择通信方式使用场合决定。
3. 可以通过电平转化芯片变为 RS232/RS485 电平。

2.4STM32F103UART框图

端口引脚:

1. TX: 数据发送端口
2. RX: 数据接收端口
3. SW_RX: 在单线和智能卡模式下接收数据,属于内部端口,没有实际的外部引脚
4. RTS: 在硬件流控制下用于指示设备准备好可以接收数据了,低电平表示可以接收数据。
5. CTS: 在硬件流控制下用于指示设备以及发送完数据了,如果是高电平那么在本次数据发送完成后会阻塞下一次的传输,只有在低电平的时候才允许下一次传输。
6. CK: 同步时钟端口,在同步通信模式下使用,用于输出同步时钟信号。
数据寄存器单元:
1. TDR: 发送数据寄存器
2. RDR: 接收数据寄存器
3. UART 外设中只有一个寄存器 USART_DR, 是一个双向寄存器,取决于 CPU 是读这个寄存器还是写这个寄存器;如果是读就是RDR ,如果是写就是 TDR
发送接收控制单元:

1. CR1/CR2/CR3 :控制寄存器,控制各种使能,比如 UART 使能、收发中断使能、 DMA使能等等。
2. SR: 状态寄存器:用来表明 UART 的收发状态和错误状态等等。
3. GTPR Smartcard IrDA 模式下专用的寄存器
波特率发生器:

1. fPCLK: 外设总线时钟, USART1 APB1 ,最高可取 72MHZ, 剩下四个在 APB2 ,最高可取36MHZ
2. USARTVIV:USART/UART 时钟分频器
3. DIV_Mantissa:BBR 寄存器的高 12bit ,用于存放波特率设置的整数部分
4. DIV_Fraction BRR 寄存器的低 4bit. 用于存放波特率设置值的小数部分,每一位对应的精度是1/2 的四次方 = 0.0625
5. 波特率计算公司: baudrate=fPCLK / USARTDIV * 16
UART 框图配置步骤:
选择需要使用的 USART/UART (根据地址映射表得到地址)
根据需要的波特率设置 BRR 寄存器
根据需求配置控制寄存器中的停止位和校验位
根据需求配置同步时钟使能位
使能 USART 的发送和接收位
根据需求使能发送和接收的中断位
使能 RCC 中的选中的 USART/UART 的时钟
使能 USART/UART
USART_DR 寄存器发送数据,读 USART_DR 寄存器接收数据

3 实现串口发送

软件流程设计:
初始化系统
        初始化 GPIO 、串口外设时钟
        初始化串口引脚
串口发送
usart.c文件
#include "stm32f10x.h"
#include "usart.h"
#include "stdio.h"

void myusart_init(void)
{
	GPIO_InitTypeDef GPIOInitStruct;
	USART_InitTypeDef USART_InitStruct;

	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE);

	
	GPIOInitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
	GPIOInitStruct.GPIO_Pin=GPIO_Pin_9;
	GPIOInitStruct.GPIO_Speed=GPIO_Speed_10MHz;
	GPIO_Init(GPIOA, &GPIOInitStruct);
	
	GPIOInitStruct.GPIO_Mode=GPIO_Mode_IPU;
	GPIOInitStruct.GPIO_Pin=GPIO_Pin_10;
	GPIO_Init(GPIOA, &GPIOInitStruct);
	
	USART_InitStruct.USART_BaudRate=115200;
	USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
	USART_InitStruct.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;
	USART_InitStruct.USART_Parity=USART_Parity_No;
	USART_InitStruct.USART_StopBits=USART_StopBits_1;
	USART_InitStruct.USART_WordLength=USART_WordLength_8b;
	

	USART_Init(USART1,&USART_InitStruct);
	USART_Cmd(USART1, ENABLE);

}
void My_Usart_Send_Byte(USART_TypeDef* USARTx,uint16_t Data)
{
	USART_SendData(USARTx, Data);
	while(USART_GetFlagStatus(USARTx,USART_FLAG_TXE)==RESET);
	
	

}
void My_Usart_Send_Sting(USART_TypeDef* USARTx,char* str)
{
		uint16_t  i=0;
		do
		{
					My_Usart_Send_Byte(USARTx,*(str+i));
					i++;
	
		
		}while(*(str+i)!='\0');
		while(USART_GetFlagStatus(USARTx,USART_FLAG_TC)==RESET);


}

main.c文件

#include "stm32f10x.h"
#include "main.h"
#include "usart.h"
#include "stdio.h"

void delay(uint16_t time)
{
		uint16_t i=0;
		while(time--)
		{
			i=12000;
			while(i--);
		}
}

int  main()
{
				myusart_init();
				My_Usart_Send_Byte(USART1,'A');
				My_Usart_Send_Byte(USART1,'B');
				My_Usart_Send_Byte(USART1,'C');
				My_Usart_Send_Sting(USART1,"wuyong \r\n");

   while(1)
	 {
	 }
		 
   
}

每按下一次复位串口发送一次数据

4 实现串口接收

实现串口中断接收和串口发送控制 LED
软件流程设计
初始化系统
        初始化GPIO 、串口外设、 LED 时钟
        初始化串口和LED 引脚
串口发送控制 LED
usart.c文件
#include "stm32f10x.h"
#include "usart.h"
#include "stdio.h"

void myusart_init(void)
{
	GPIO_InitTypeDef GPIOInitStruct;
	USART_InitTypeDef USART_InitStruct;
	NVIC_InitTypeDef NVIC_InitStruct;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	GPIOInitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
	GPIOInitStruct.GPIO_Pin=GPIO_Pin_9;
	GPIOInitStruct.GPIO_Speed=GPIO_Speed_10MHz;
	GPIO_Init(GPIOA, &GPIOInitStruct);
	
	GPIOInitStruct.GPIO_Mode=GPIO_Mode_IPU;
	GPIOInitStruct.GPIO_Pin=GPIO_Pin_10;
	GPIO_Init(GPIOA, &GPIOInitStruct);
	
	USART_InitStruct.USART_BaudRate=115200;
	USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
	USART_InitStruct.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;
	USART_InitStruct.USART_Parity=USART_Parity_No;
	USART_InitStruct.USART_StopBits=USART_StopBits_1;
	USART_InitStruct.USART_WordLength=USART_WordLength_8b;
	
	NVIC_InitStruct.NVIC_IRQChannel=USART1_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=0;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority=0;
	NVIC_Init(&NVIC_InitStruct);
	
	USART_Init(USART1,&USART_InitStruct);
	USART_Cmd(USART1, ENABLE);
	USART_ITConfig(USART1,USART_IT_RXNE, ENABLE);
}
void My_Usart_Send_Byte(USART_TypeDef* USARTx,uint16_t Data)
{
	USART_SendData(USARTx, Data);
	while(USART_GetFlagStatus(USARTx,USART_FLAG_TXE)==RESET);
	
	

}
void My_Usart_Send_Sting(USART_TypeDef* USARTx,char* str)
{
		uint16_t  i=0;
		do
		{
					My_Usart_Send_Byte(USARTx,*(str+i));
					i++;
	
		
		}while(*(str+i)!='\0');
		while(USART_GetFlagStatus(USARTx,USART_FLAG_TC)==RESET);


}
int fputc(int ch,FILE *p)
{
		USART_SendData(USART1,(u8)ch);
		while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
		return ch;
}

void USART1_IRQHandler()
{
			char str;
			if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)
			{
				
					
				str=USART_ReceiveData(USART1);
					
				printf("receive:%c  \r\n",str);
				if(str=='0')
				{
				
						GPIO_ResetBits(GPIOA,GPIO_Pin_1);
						printf("led open  \r\n");


				}
				if(str=='1')
				{
				
			    	GPIO_SetBits(GPIOA,GPIO_Pin_1);
						printf("led close  \r\n");

				}
				
			  USART_ClearITPendingBit(USART1,USART_IT_RXNE);

			}
			



}	

main.c文件

#include "stm32f10x.h"
#include "main.h"
#include "led.h"
#include "usart.h"
#include "stdio.h"


int  main()
{
				myusart_init();
				My_Usart_Send_Byte(USART1,'A');
				My_Usart_Send_Byte(USART1,'B');
				My_Usart_Send_Byte(USART1,'C');
				My_Usart_Send_Sting(USART1,"wuyong \r\n");
				LED_Init();

				
	    	GPIO_SetBits(GPIOA,GPIO_Pin_1);



   while(1)
	 {		 
	 }
		 
   
}

串口接收到0,灯亮

串口接收到1,灯灭

相关文章:

  • vue3中watch 函数参数说明
  • db_join连接语句
  • Ubuntu 22.04 安装向日葵远程控制
  • 电路租用和专线
  • [Linux]从零开始的STM32MP157 Linux内核移植
  • 只出现一次的数字
  • 为AI聊天工具添加一个知识系统 之150 设计重审 之15 完整方案及评估 之3
  • 【mybatis使用小知识合集持续更新】
  • 283.移动零解题记录
  • 深入解析 MyBatis-Plus 批量操作:原理、实现与性能优化
  • Matplotlib.day16
  • Nextjs15 - 什么是CSR、SSR、SSG和ISR
  • centos 7 搭建ftp 基于虚拟用户用shell脚本搭建
  • k8s存储介绍(六)StorangeClass
  • Redis :command not allowed when used memory
  • a, b = map(int, input().split()) 从用户输入中读取两个整数
  • 耘想Docker LinNAS,颠覆传统存储体验!
  • muduo库的思路梳理
  • 前端使用WPS WebOffice 做在线文档预览与编辑
  • Redux,React-redux。基础
  • 跨越时空的“精神返乡”,叶灵凤藏书票捐赠上海文学馆
  • 让“五颜六色”面孔讲述上海故事,2025年上海城市推荐官开启选拔
  • 深圳市政协原副主席王幼鹏被“双开”
  • 4月证券私募产品备案量创23个月新高,股票策略占比超六成
  • 匈牙利外长称匈方已驱逐两名乌克兰外交官
  • 第一集|《刑警的日子》很生活,《执法者们》有班味