单片机--USART

【1】通信的基础知识

  1. 通信:至少有收发两方
  2. 通信方式的划分

同步通信:通信双方根据同步信号通信,比如双方有一个共同的时钟信号(SPI同步通信)

       优点:安全性高

异步通信:通信双方有自己的独立系统时钟,大家约定好通信的速度。异步通信不需要同步信号,但并不是说通信的过程不同步了。(UART)

         缺点:存在误差

 

 串行通信:指的是同一时刻只能发送一个bit位,因此只需要一根线也可以

       优点:占用引脚资源少

       缺点:速率慢

并行通信:指的是同一时刻可以发送或者接收多个bit位,所以需要多根数据线

       优点:速率快

       缺点:占用引脚资源多

 单工:要么收,要么发,只能做接受设备或者发送设备。比如:收音机

半双工:可以收,可以发,但是同一时刻只能收或发。比如:对讲机

全双工:可以在同一时刻即接收又发送。比如:手机

【2】USART 

    Universal Synchonous Asynchronous receiver transmitter 通用同步异步接收发射机

  中文参考手册 564页

           USART:   支持同步\异步通信、全双工、串行

            UART :没有信号线,只支持异步通信、全双工、串行

【3】串口通信协议

          数据帧格式:

              空闲状态:信号线保持高电平

              起始位:1位   低电平表示数据包的起始

              数据位:8位or9位(一般为8位,添加符号位的话为9位)

              校验位(可选):奇偶校验

                       奇校验:

                               数据位上的1的个数 + 校验位上1的个数 = 奇数

                       偶校验:

                               数据位上的1的个数 + 校验位上1的个数 = 偶数

              停止位:1位  将电平信号拉高,代表一个数据包发送结束,回到空闲状态。

【4】相关寄存器 

   串口控制寄存器 

             (设备功能初始化、通信帧格式配置)

                USART_CR1  USART_CR2  USART_CR3  

   波特率寄存器

             USART_BRR   

   中断和状态寄存器 

             USART_ISR

   数据发送寄存器  

           USART_TDR

数据接收寄存器 

         USART_RDR

【5】 USART功能框图

Tx:数据发送端

Rx:数据接收端

流控概念

     在两个设备正常通信时,由于处理速度不同,就存在这样一个问题,有的快,有的慢,在某些情况下,就可能导致丢失数据的情况。如台式机与单片机之间的通讯,接收端数据缓冲区已满,则此时继续发送来的数据就会丢失。流控制能解决这个问题

nRTS:请求以发送(Request To Send),n表示低电平有效。当本设备准备好接收新数据时就会将nRTS变成低电平;当接收寄存器已满时,nRTS将被设置为高电平。

nCTS:清除以发送(Clear To Send) 为输入信号,低电平有效。用于判断是否可以向对方发送数据,低电平说明本设备可以向对方发送数据。

该引脚只适用于硬件流控制

SCLK:发送器时钟输出引脚。这个引脚仅适用于同步模式。

发送过程:由CPU和DMA向数据发送寄存器(TDR)中写入要发送的数据,由发送移位寄存器将数据按位移到发送端口输出。

接收过程:由CPU和DMA读取接收数据寄存器(RDR)中的数据。

【6】串口发送实验

          实验要求

                        通过单片机向电脑(串口助手)发送数据

         1.观察实物

              找到通信接口    丝印“P4”

         2.分析原理图

             CH340 : 电平转换芯片,可以转换TTL电平-USB电平。

 数据选择器/多路复用器

 

3.STM32CubeMX配置

  1. 寄存器方式编写发送接受一个字节的函数

//写一个单字节发送的函数
void put(uint8_t ch)
{
    //while(USART1->ISR & 0x40==0){}  0x40=0100 0000 循环为0 说明发送数据寄存器不为空
	while(!(USART1->ISR & 1<<7)){}
	//判断发送数据寄存器是不是空了
	USART1->TDR=ch;
	//将数据写入到TDR寄存器中
}
int get()
{
	uint8_t ch;
  while(!(USART1->ISR & 1<<5)){}
	//判断接受数据寄存器是不是空了
	ch=USART1->RDR;
	//将数据从RDR寄存器中读出来
	return ch;
}
  1. 寄存器方式编写发送接受一个字节的函数

 HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, 

                                       uint32_t Timeout)

功能:串口发送数据

参数:huart :串口选择(USART1)         pData:需要发送的数据   

         Size:发送多少个数据                       Timeout:超时时间

返回值:成功返回HAL_OK 失败返回HAL_TIMEOUT

 HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size,

                                     uint32_t Timeout)

功能:串口接收数据函数

参数:huart :串口选择(USART1)          pData :接收数据的地址   

          Size:发送多少个数据                      Timeout:超时时间

返回值:成功 :返回HAL_OK      失败 :返回HAL_TIMEOUT

HAL_UART_Receive(&huart1,buf,2,100);
HAL_UART_Transmit(&huart1,buf,strlen(buf),100);
memset(buf,0,sizeof(buf));

7、不定长接收

声明
uint8_t buf[128]={"0 "};//数据缓存区
uint8_t byte;//单个字节缓存区
uint8_t len=0;//接收到的数据长度
写在while
if(HAL_UART_Receive(&huart1,&byte,1,100)==HAL_OK)
//判断接收一个字节是否成功
	{
	   if(byte=='\n')//判断是否结束
			{//如果结束处理数据
				HAL_UART_Transmit(&huart1,buf,len,100);//原封不动回回去
				memset(buf,0,len);//清空缓存区
				len=0;	//长度清0
				}
		else//如果没有接收完成
		{
			buf[len++]=byte;//继续接收,把接收到的数据存储到buf
		 }
}

8、重定向

//printf的重定向
int fputc(int ch,FILE *f)
{
  while(!(USART1->ISR & 1<<7)){}
	//判断发送数据寄存器是不是空了
	USART1->TDR=ch;
	//将数据写入到TDR寄存器中
}
//scanf的重定向
int fgetc(FILE *f)
{
	uint8_t ch;
  while(!(USART1->ISR & 1<<5)){}
	//判断接受数据寄存器是不是空了
	ch=USART1->RDR;
	//将数据从RDR寄存器中读出来
	return ch;
}
scanf("%s",buf);
printf("%s",buf);
HAL_Delay(500);

扩展:

简介: 

 74LS138 为3 线-8线译码器,共有 54LS138和 74LS138 两种线路结构型式。54LS138为军用,74LS138为民用

工作原理:

①当一个选通端(E1)为高电平,另两个选通端(E2)和(E3)为低电平时,可将地址端(A0、A1、A2)的二进制编码在Y0至Y7对应的输出端以低电平译出。(即输出为Y0至Y7的非)比如:A2A1A0=110时,则Y6输出端输出低电平信号。

 

  1. 编写呼吸灯
  2. 串口发送ON开LED,发送OFF关LED或者(0X550X440XFF表示开灯,0X550X660XFF表示关灯)注:包头 0X55  包尾:0XFF  数据:0X44表示开灯  0X66表示关灯
void ledOn(void)
{
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
	printf("LED ON\n");
}

void ledOff(void)
{
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
	printf("LED OFF\n");
}

void ledHuu(void)
{
	printf("LED 呼吸\n");
	for(int i = 0; i < 3; i++)
	{
		for(int i = 2000; i > 0; i--)
		{
			HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
			delay(i);
			HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
			delay(2000-i);
		}
		for(int i = 0; i < 2000; i++)
		{
			HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
			delay(2000-i);
			HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
			delay(i);
		}
	}
}

void recvProcess(void)
{
	if(buf[0] == 0x55 && buf[2] == 0xFF)
	{
		if(buf[1] == 0x44)
			ledOn();
		else if(buf[1] == 0x66)
			ledOff();
		else if(buf[1] == 0xaa)
			ledHuu();
	}
	else if(buf[0] == 'O')
	{
		if(buf[1] == 'N')
			ledOn();
		else if(buf[1] == 'F')
			ledOff();
	}
	else if(buf[0] == 'H')
		ledHuu();
	memset(buf, 0, sizeof(buf));
}
1.呼吸灯
//自定义延时函数
void Delay(int i)
{
	while(i--);
}



int main()
{
while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		for(int i=0;i<3000;i++)
		{
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET);
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_RESET);
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,GPIO_PIN_RESET);
			Delay(i);
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET);
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,GPIO_PIN_SET);
			Delay(3000-i);
		}
		for(int i=3000;i>0;i--)
		{
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET);
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_RESET);
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,GPIO_PIN_RESET);
			Delay(i);
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET);
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,GPIO_PIN_SET);
			Delay(3000-i);
		}
  }
}
 //2.开关灯控制

#include <stdio.h>
#include <string.h>
uint8_t buf[32]={"0"};//数据缓存区
uint8_t byte;//单个字节缓存区
uint8_t len=0;//接收到的数据长度


while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		if(HAL_UART_Receive(&huart1,&byte,1,100)==HAL_OK)
	   {
		    if(byte=='N')
				{
           HAL_UART_Transmit(&huart1,buf,len,100);
					 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2,GPIO_PIN_RESET);
					 memset(buf,0,len);
					 len=0;
				}
				if(byte=='F')
				{
					HAL_UART_Transmit(&huart1,buf,len,100);
					HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2,GPIO_PIN_SET);
					memset(buf,0,len);
					len=0;
				}
		 }
  }
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
USART-GPU单片机程序是一种利用USART通信协议与GPU进行数据交换的单片机程序。USART是通用同步异步收发传输器的简称,是一种串行通信协议,用于在微控制器和外部设备之间进行数据传输。GPU则是图形处理器的缩写,负责处理计算机图形和图像相关的任务。 在USART-GPU单片机程序中,单片机通过USART通信协议与GPU进行数据传输。它首先建立USART通信连接,并初始化对应的USART通信端口和波特率。然后,单片机将需要传输的数据通过USART协议封装成数据包,并发送给GPU。GPU接收到数据包后,解析数据并进行相应的图形和图像处理操作。处理完成后,GPU将结果数据封装成数据包,并通过USART协议将数据包发送给单片机单片机接收到数据包后,解析数据,并根据需要进行后续的操作或显示。 USART-GPU单片机程序的应用场景很广泛。例如,可以用于嵌入式系统中的图形显示和图像处理,可以通过单片机与GPU进行数据交互,实现显示器的驱动和图像的处理。另外,它还可以应用于机器人、智能仪表、智能家居等领域,利用GPU的强大计算能力和图形处理能力,实现更加复杂的计算和图形展示任务。 总之,USART-GPU单片机程序是一种利用USART通信协议与GPU进行数据交换的单片机程序,通过USART协议建立通信连接,实现单片机与GPU之间的数据传输和互操作。它在嵌入式系统、机器人、智能仪表等领域具有广泛的应用前景。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值