学习记录:USART—串口通讯

目录

1.串口通讯协议简介

1.1物理层

1.2 电平标准

2.协议层

 3.printf函数的支持代码

 4.usart.h程序

 5.main.c主函数

6.实验现象 


1.串口通讯协议简介

对于通讯协议,我们也以分层的方式来理解,最基本的是把它分为物理层和协议层。物理层规定通讯系统中具有机械、电子功能部分的特性,确保原始数据在物理媒体的传输。协议层主要规定通讯逻辑,统一收发双方的数据打包、解包标准。 

1.1物理层

主要是了解:RS-232 标准,RS-232 标准主要规定了信号的用途、通讯接口以及信号的电平标准。 

使用RS-232标准的串口设备间常见的通讯结构,如下图所示

在上面的通讯方式中,两个通讯设备的“DB9 接口”之间通过串口信号线建立起连接,串口信号线中使用“RS-232 标准”传输数据信号。由于 RS-232 电平标准的信号不能直接被控制器直接识别,所以这些信号会经过一个“电平转换芯片”转换成控制器能识别的“TTL 标准”的电平信号,才能实现通讯。 

1.2 电平标准

根据通讯使用的电平标准不同,串口通讯可分为 TTL 标准及 RS-232 标准;

常见的电子电路中常使用 TTL 的电平标准,理想状态下,使用 5V 表示二进制逻辑 1,使用 0V 表示逻辑 0;而为了增加串口通讯的远距离传输及抗干扰能力,RS-232使用-15V 表示逻辑 1, +15V 表示逻辑 0。使用 RS232 与 TTL 电平校准表示同一个信号时的对比,如下图所示。

因为控制器一般使用 TTL 电平标准,所以常常会使用 MA3232 芯片对 TTL 及 RS-232 电平的信号进行互相转换。

2.协议层

串口通讯的数据包由发送设备通过自身的 TXD 接口传输到接收设备的 RXD 接口。在串口通讯的协议层中,规定了数据包的内容,它由启始位、主体数据、校验位以及停止位组成,通讯双方的数据包格式要约定一致才能正常收发数据,

 3.printf函数的支持代码

//加入以下代码,支持printf函数,而不需要选择use MicroLIB	  
#if 1
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 
{ 
	int handle; 

}; 

FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) 
{ 
	x = x; 
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{      
	while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
    USART1->DR = (u8) ch;      
	return ch;
}
#endif 

 4.usart.h程序

定义最大接收字节数 200;

#define USART_REC_LEN  			200  

接收缓冲,最大USART_REC_LEN个字节.末字节为换行符;

extern u8  USART_RX_BUF[USART_REC_LEN]; 

接收状态标记  ;

extern u16 USART_RX_STA;

使能(1)/禁止(0)串口1接收 ;

#define EN_USART1_RX 			1		

usart.c和usart.h函数程序在专栏Stm32学习笔记中的博客学习记录:串口通信和遇到的错误解决方法 有写。

 5.main.c主函数

#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关注Bitter tea seeds\r\n");
					printf("USART—串口通讯\r\n\r\n");
				}
				if(times%200==0)printf("请输入数据,以回车键结束\n");  
				if(times%30==0)LED0=!LED0;//闪烁LED,提示系统正在运行.
				delay_ms(10);   
			}
		}	 
}

首先判断全局变量 USART_RX_STA 的最高位是否为 1,如果为 1 的话,那么代表前一次数据接收已经完成,接下来就是把我们自定义接收缓冲的数据发送到串口。

while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);

上述代码就是我们发送一个字节之后之后,要检测这个数据是否已经被发送完成了。

6.实验现象 

 

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
以下是一个使用USART1串口通信的STM32完整函数的示例: ``` #include "stm32f4xx.h" void USART1_Init(void) { USART_InitTypeDef USART_InitStruct; GPIO_InitTypeDef GPIO_InitStruct; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_USART1); //TX GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_USART1); //RX USART_InitStruct.USART_BaudRate = 9600; 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 USART1_SendChar(uint16_t ch) { while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET){} USART_SendData(USART1, (uint8_t) ch); } uint16_t USART1_ReceiveChar(void) { while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET){} return (uint16_t)USART_ReceiveData(USART1); } ``` 使用USART1串口通信时,需要按照以下步骤进行初始化: - 开启USART1和GPIOB的时钟 - 设置GPIOB Pin6和Pin7的模式为AF模式 - 配置USART1的波特率、数据位、停止位及校验位等参数 - 启用USART1 在发送数据时,需要使用`USART1_SendChar`函数,该函数的输入参数为uint16_t类型,但实际只会发送其中的低8位。 在接收数据时,需要使用`USART1_ReceiveChar`函数,该函数返回uint16_t类型的数据,但实际接收到的只有其中的低8位。如果需要接收多个字节,需要使用循环调用该函数进行数据接收。 需要注意的是,在发送或接收数据时,需要先检查USART是否处于空闲状态(即判断`USART_FLAG_TXE`或`USART_FLAG_RXNE`是否被置位),否则可能会出现通信错误。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bitter tea seeds

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值