基于STM32标准库的USART串口通信

一. 了解串口协议和RS-232标准,以及RS232电平与TTL电平的区别;了解"USB/TTL转232"模块(以CH340芯片模块为例)的工作原理。

串口通讯(Serial Communication)是一种设备间非常常用的串行通讯方式,因为它简单、便捷,因此大部分电子设备都支持该通讯方式,电子工程师在调试设备时也经常使用该通 讯方式输出调试信息。

RS-232 标准主要规定了信号的用途,通讯接口以及信号的电平标准。
根据通讯使用的电平标准不同,串口通讯可分为 TTL标准和 RS-232标准
在这里插入图片描述

从表格中不难看出,两种标准划分的逻辑电压不同。在电子电路中常使用 TTL 的电平标准,理想状态下,使用 5V 表示二进制逻辑 1,使用 0V 表示逻辑 0;而为了增加串口通讯的远距离传输及抗干扰能力,它使用-15V表示逻辑 1,+15V 表示逻辑 0
USB转串口即实现计算机USB接口到物理串口之间的转换。可以为没有串口的计算机或其他USB主机增加串口,使用USB转串口设备等于将传统的串口设备变成了即插即用的USB设备。
CH340 是一个USB 总线的转接芯片,实现USB 转串口、USB 转IrDA 红外或者USB 转打印口。
在串口方式下,CH340 提供常用的MODEM联络信号,用于为计算机扩展异步串口,或者将普通的串口设备直接升级到USB 总线。有关USB 转打印口的说明请参考手册(二)CH340DS2。
在红外方式下,CH340 外加红外收发器即可构成USB 红外线适配器,实现SIR 红外线通讯。
特点:
● 全速USB 设备接口,兼容USB V2.0,外围元器件只需要晶体和电容。
● 仿真标准串口,用于升级原串口外围设备,或者通过USB 增加额外串口。
● 计算机端Windows 操作系统下的串口应用程序完全兼容,无需修改。
● 硬件全双工串口,内置收发缓冲区,支持通讯波特率50bps~2Mbps。
● 支持常用的MODEM 联络信号RTS、DTR、DCD、RI、DSR、CTS。
● 通过外加电平转换器件,提供RS232、RS485、RS422 等接口。
● 支持IrDA 规范SIR 红外线通讯,支持波特率2400bps 到115200bps。
● 由于是通过USB 转换的串口,所以只能做到应用层兼容,而无法绝对相同。
● 软件兼容CH341,可以直接使用CH341 的驱动程序。
● 提供SSOP-20 无铅封装,兼容RoHS。

二. 安装 stm32CubeMX,配合Keil,使用HAL库(或标准库)方式,设置USART1 波特率为115200,1位停止位,无校验位.

1)STM32系统给上位机(win10)连续发送“hello windows!”。win10采用“串口助手”工具接收。

我们首先进行标准库中USART1的函数配置
以前做过
参考链接:http://t.csdnimg.cn/n8j3n
我们打开工程模板,在Hardware组里新建“Serial.c"和”Serial.h"两个文件
在这里插入图片描述

注意添加路径
在这里插入图片描述

然后写头文件内容
在这里插入图片描述

在”Serial.c"函数中写入以下
在这里插入图片描述

写入一个“Serial_Init”函数,用于配置基本的USART和GPIO

首先是打开APB使能时钟,
在这里插入图片描述

接下来配置GPIO口,打开GPIOA的PA9引脚,作为数据发送。模式设置为复用推挽输出模式


GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

接下来是配置USART串口通信,我们选择USART1作为串口,同样建立结构体,设置波特率为9600,模式为仅发送,0校验位,1停止位,8数据位。编写如下:

USART_InitTypeDef USART_InitStruture;
	USART_InitStruture.USART_BaudRate=9600;
	USART_InitStruture.USART_HardwareFlowControl=USART_HardwareFlowControl_None ;
	USART_InitStruture.USART_Mode=USART_Mode_Tx;
	USART_InitStruture.USART_Parity=USART_Parity_No ;
	USART_InitStruture.USART_StopBits=USART_StopBits_1 ;
	USART_InitStruture.USART_WordLength=USART_WordLength_8b;
	USART_Init(USART1,&USART_InitStruture);

最后一步,把void Serial_Init(void);放到头文件里声明一下。
自动发送字符串
我们将字符串的每个字符放在一个数组的每个元素中,发送时发送数组即可

首先我们先封装发送一个字符的函数,如下

void Serial_SendByte(uint8_t Byte)
{
	USART_SendData(USART1, Byte);
	while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}

之后的所有发送方式都是基于发送一个字符来实现的。然后我们封装一个发送数组的函数

void Serial_SendArray(uint8_t *Array, uint16_t Length)
{
	uint16_t i;
	for (i = 0; i < Length; i ++)
	{
		Serial_SendByte(Array[i]);
	}
}

至此,函数就写完了。接下来只需要在主函数中定义一个数组,把字符串中的每个字符填到数组里面,再调用上面写的发送数组函数即可
主函数编写
基于利用发送字符串的方式发送数据,我们将主函数编写如下:

int main(void)
{
	Serial_Init();

	while (1)
	{
		Serial_SendString("Hello,Windows!!");
		Serial_SendString("\r\n");
		Delay_ms(1000);
		
	}
}

烧录然后运行
在这里插入图片描述

要将上面的波特率和那些参数与自己代码写的一致

波形测试观察
keil MDK自带的调试模式可以通过输出波形来观察串口的电平变化情况,关于调试方面的配置之前已经讲过了,这里就把图列出来:

在这里插入图片描述

波形结果
在这里插入图片描述

2)在完成以上任务基础,继续扩展功能:当上位机给stm32发送一个字符“#”后,stm32暂停发送“hello windows!”;发送一个字符“*”后,stm32继续发送;

配置NVIC控制USART1触发中断
在原有“Serial.c"中Serial_Init()代码的基础上,我们需要进行以下修改

首先开启GPIOA的PA10端口。

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

然后加上打开USART中断,配置NVIC

USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
	
	//配置NVIC
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//选择分组2
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel= USART1_IRQn;//USART1在NVIC中的通道
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE ;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
	NVIC_Init(&NVIC_InitStructure);

接下来是编写中断函数,标准库给出了控制USART1中断的函数USART1_IRQHandler()

void USART1_IRQHandler(void)//中断函数
{
	if(USART_GetFlagStatus(USART1,USART_IT_RXNE)==SET)//判断标志位
	{
		Serial_RxData=USART_ReceiveData(USART1);//读取PC发来的数据
		Serial_RxFlag=1;//标志位置1
		
		USART_ClearITPendingBit(USART1,USART_IT_RXNE);//清除中断函数标志位
	}
}
uint8_t Serial_GetRxFlag(void)//读后自动清除
{
	if(Serial_RxFlag==1)
	{
		Serial_RxFlag=0;
		return 1;
	}
	else return 0;
	
}
uint8_t Serial_GetRxData(void)//将中断读取的值返回到主函数中
{
	return Serial_RxData;
	
}
 主函数代码
我们在头文件中加入我们新编写的函数

```cpp
int main(void)
{
	
	Serial_Init();
	uint8_t RxData1;//定义接收变量,用于接收从PC端发来的数据
  uint16_t flag=0;//定义标志位,用于打断或开启发送
	while (1)
	{
		
		if (Serial_GetRxFlag() == 1)
		{
			RxData1 = Serial_GetRxData();//接收数据
		if(RxData1=='*')
		{
				flag=1;//标志位置1
			while(flag==1)//开始发送
			{
				Serial_SendString("Hello,Windows!");
				Serial_SendString("\r\n");
//				OLED_ShowString(1, 1, "Hello,Windows!");
				Delay_ms(1000);
				
				RxData1 = Serial_GetRxData();//再读取一次接收端数据
				if(RxData1=='#')//若为’#‘,跳出循环
				{
					flag=0;//标志位变为0
				}
				
			}	
			
		}
		else if(RxData1=='#')//输入#,单片机停止发送
		{
			Serial_SendString("Stop!!! Press '*' to continue!");
//			OLED_ShowString(1, 1, "                  ");
//			OLED_ShowString(1, 1, "Stop!!!");
			Serial_SendString("\r\n");
		}
		else //输入其他字符,显示错误
		{
			Serial_SendString("Wrong!!!");
//			OLED_ShowString(1, 1, "                  ");
//			OLED_ShowString(1, 1, "Wrong!!!");
			Serial_SendString("\r\n");
		}
		}
	}

	
	
}

三.总结

通过USART串口通信实验,让我知道串口通信是指外设和计算机间,通过数据信号线、地线等,按位进行传输数据的一种通信方式,属于串行通信方式。串口是一种接口标准,它规定了接口的电气标准,没有规定接口插件电缆以及使用的协议。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值