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

UART串口通讯---STM32

描述:STM32F103C8T6单片机与目标设备使用串口通讯;下面工程代码可以直接复制使用;

一,简介

        串口通讯(Serial Communication)是一种设备间非常常用的串行通讯方式,因为它简单便捷,因此大部分电子设备都支持该通讯方式,其通讯协议可分层为协议层和物理层。物理层规定通信协议中具有机械、电子功能的特性,从而确保原始数据在物理媒体的传播;协议层主要规定通讯逻辑,统一双方的数据打包、解包标准。通俗的讲物理层规定我们用嘴巴还是肢体交流,协议层规定我们用中文还是英文交流;

STM32的UART特点:


                1)全双工异步通信;
                2)分数波特率发生器系统,提供精确的波特率。发送和接受共用的可编程波特率,最高可达4.5Mbits/s;
                3)可编程的数据字长度(8位或者9位);
                4)可配置的停止位(支持1或者2位停止位);
                5)可配置的使用DMA多缓冲器通信;
                6)单独的发送器和接收器使能位;
                7)检测标志:① 接受缓冲器  ②发送缓冲器空 ③传输结束标志;
                8)多个带标志的中断源,触发中断;
                9)其他:校验控制,四个错误检测标志

STM32串口通信基础:


        STM32的串口通信接口有两种,分别是:UART(通用异步收发器)、USART(通用同步异步收发器)。而对于大容量STM32F10x系列芯片,分别有3个USART和2个UART。
        UART引脚连接方法:RXD-----数据输入引脚,数据接受;TXD-----数据发送引脚,数据发送。

      对于两个芯片之间的连接,两个芯片GND共地,同时TXD和RXD交叉连接。这里的交叉连接的意思就是,芯片1的RxD连接芯片2的TXD,芯片2的RXD连接芯片1的TXD。这样,两个芯片之间就可以进行TTL电平通信了。

串口通讯的过程:

 

二、工程代码

串口操作的一般步骤:


        1)GPIO时钟使能,串口时钟使能。调用函数:RCC_APB2PeriphClockCmd();
        2)串口复位(这一步不是必须的)。调用函数:USART_DeInit();
        3)GPIO外设功能下的端口模式设置。调用函数:GPIO_Init();Tx(发送引脚)配置为复用推挽输出(GPIO_Mode_AF_PP)用来发送数据,Rx(接收引脚)配置为浮空输入(GPIO_Mode_IN_FLOATING)用来接收数据。
        4)串口参数初始化。调用函数:USART_Init();
        5)开启中断并且初始化NVIC(如果需要开启中断才需要这个步骤)。调用函数:NVIC_Init();USART_ITConfig();
        6)使能串口。调用函数:USART_Cmd();
        7)编写中断处理函数。调用函数:USARTx_IRQHandler();
        8)串口数据收发。调用函数:USART_SendData();USART_ReceiveData();
        9)串口传输状态获取。调用函数:USART_GetFlagStatus();USART_ClearITPendingBit()

 代码:

uart.c

#include "stm32f10x.h"
#include "usart2.h"	  
#include "string.h"

/*
A2	--->	TX
A3	--->	RX
*/


u8 	USART2_RX_BUF[USART2_REC_LEN];
u16 USART2_RX_STA = 0;



void USART2_Init(void){
  //GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);												//使能USART1,GPIOA时钟
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);	
	//USART1_TX   GPIOA.2
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; 																		//PA2接串口输出(Tx)脚
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;																//复用推挽输出
  GPIO_Init(GPIOA, &GPIO_InitStructure);																				//初始化GPIO
   
  //USART1_RX	  GPIOA.3初始化
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;																			//PA3接串口输入(Rx)脚
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;													//浮空输入
  GPIO_Init(GPIOA, &GPIO_InitStructure);																				//初始化GPIO

  //Usart1 NVIC 配置
  NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;												//抢占优先级1
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;														//子优先级1
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;																//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);																								//根据指定的参数初始化VIC寄存器
  
   //USART 初始化设置

	USART_InitStructure.USART_BaudRate = 115200;																		//串口波特率
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;											//字长为8位数据格式
	USART_InitStructure.USART_StopBits = USART_StopBits_1;													//一个停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;															//无奇偶校验位
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件数据流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;									//收发模式

  USART_Init(USART2, &USART_InitStructure); 																			//初始化串口1
  USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);																	//开启串口接受中断
  USART_Cmd(USART2, ENABLE);                    																	//使能串口1 

}


// 
 /
void USART2_IRQHandler(void)                	//串口1中断服务程序
	{
	u8 Res;

	if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)  					//接收中断(接收到的数据必须是0x0d 0x0a结尾)
	{
		Res =USART_ReceiveData(USART2);																//读取接收到的数据
		
		if((USART2_RX_STA&0x8000)==0)																	//接收未完成
			{
			if(USART2_RX_STA&0x4000)																		//接收到了0x0d
				{
				if(Res!=0x0a)USART2_RX_STA=0;															//接收错误,重新开始
				else USART2_RX_STA|=0x8000;																//接收完成了 
				}
			else 																												//还没收到0X0D
				{	
				if(Res==0x0d)USART2_RX_STA|=0x4000;
				else
					{
					USART2_RX_BUF[USART2_RX_STA&0X3FFF]=Res ;
					USART2_RX_STA++;
					if(USART2_RX_STA>(USART2_REC_LEN-1))USART2_RX_STA=0;		//接收数据错误,重新开始接收	  
					}		 
				}
			}   		 
     } 
}
	


 /**
  * 函    数:串口发送一个字节
  * 参    数:Byte 要发送的一个字节
  * 返 回 值:无
  */
void USART2_SendChar(char ch) {
    // 发送字符数据 ch 到 USART3
    USART_SendData(USART2, (u8) ch);//将字节数据写入数据寄存器,写入后USART自动生成时序波形
    // 等待发送完成
    while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);		//等待发送完成
		/*下次写入数据寄存器会自动清除发送完成标志位,故此循环后,无需清除标志位*/
}
 
/**
  * 函    数:串口发送一个数组
  * 参    数:Array 要发送数组的首地址
  * 参    数:Length 要发送数组的长度
  * 返 回 值:无
  */
void USART2_SendArray(u8 *Array, u16 Length)
{
	u16 i;
	for (i = 0; i < Length; i ++)		//遍历数组
	{
		USART2_SendChar(Array[i]);		//依次调用Serial_SendByte发送每个字节数据
	}

}

/**
  * 函 数:串口发送一个字符串
  * 参 数:str 要发送的字符串
  * 返 回 值:无
  */
void USART2_SendString(const char *str) {

    while (*str) {
        USART2_SendChar(*str);  			// 发送当前字符
        str++;  											// 移动到下一个字符
    }
    // 发送换行和回车符
    USART2_SendChar('\r');  					// 发送回车符
    USART2_SendChar('\n');  					// 发送换行符
}

/***函数:串口接收函数**/
u16 CheckReceive(void) 
{
	u8 data; 												// 定义一个无符号 8 位整数型变量 data,用于存储接收到的数据
  char buffer[8];									// 定义一个长度为 8 的字符数组 buffer,用于存储接收到的数据
  int i = 0; 											// 定义一个整型变量 i,用于索引 buffer 数组
    
																										
  while (i < 7) 																								// 数据发送完成会返回一个“OK”进入一个循环,循环条件是 i 小于 7
	{																							
		if (USART_GetFlagStatus(USART2, USART_FLAG_RXNE) != RESET) 	// 检查 USART2 接收缓冲区是否非空,即是否有数据可读
			{																				
				data = (u8)USART_ReceiveData(USART2);										// 这个函数会接受最近串口收到的消息,并返回;如果接收缓冲区非空,则读取接收到的数据并存储到 data 变量中																				
        buffer[i++] = data;																			// 将读取到的数据存储到 buffer 数组中,并将索引 i 自增
       }
   }
	
    buffer[i] = '\0';																						// 在 buffer 数组末尾添加字符串结束标志 '\0'
	 
    if (strcmp(buffer, "OK") == 0) return 0;
		else return 1;

}

uart.h

#ifndef __USART2_H
#define __USART2_H
#include "stdio.h"	
#include "sys.h" 
//技术支持:

#define USART2_REC_LEN  			200  					//定义最大接收字节数 200
#define EN_USART2_RX 					1							//使能(1)/禁止(0)串口1接收
	  

extern char commands[][100];  								// 声明数组 commands

extern u8  USART2_RX_BUF[USART2_REC_LEN]; 	//接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 
extern u16 USART2_RX_STA;         					//接收状态标记	


void USART2_Init(void);
void USART2_SendChar(char ch);
void USART2_SendArray(u8 *Array, u16 Length);
void USART2_SendString(const char *str);
u16  CheckReceive(void);

#endif




 


http://www.kler.cn/a/430634.html

相关文章:

  • Mysql 查询性能调优总结
  • week 11 - BCNF
  • React第十八节 useEffect 用法使用技巧注意事项详解
  • Vue零基础必学教程(16) 计算属性
  • Golang的容器化技术实践总结
  • 活着就好20241225
  • 初次使用uniapp编译到微信小程序编辑器页面空白,真机预览有内容
  • 2024.12.10总结
  • zsh配置
  • Word中的公式域
  • SQL项目实战与综合应用——项目设计与需求分析
  • 鸿蒙面试---1208
  • Muduo网络库解析---事件循环模块
  • Java 基础之 XQuery:强大的 XML 查询语言
  • 【C++指南】类和对象(七):友元
  • html小白初学
  • go语言zero框架对接阿里云消息队列MQ的rabbit的配置与调用
  • Java项目--仿RabbitMQ的消息队列--需求分析
  • PVE修改IP地址
  • 基于 SSM 的个性化商铺系统:先进架构保障系统稳定性
  • el-table手动触发懒加载
  • 【优选算法】哈希表
  • 文件下载和图片预览 Blob FileReader
  • elementUI修改table样式
  • SQL面试题——连续问题 连续点击三次用户
  • 5G中的随机接入过程可以不用收RAR?