STM32串口通信实例及详细代码解析
这里我们使用串口1,来通过我们发送的数据来决定去实现相应的操作。
示例是当单片机串口接收到数据后控制LED1的亮灭,并且将数据发送到上位机
首先我们的LED1的初始化,当然PB0连接的是蜂鸣器,这边就一起配置,首先初始化这俩个引脚。
LED1灯和BUZZER的配置和相关函数
led.c
#include "stm32f10x.h" // Device header
#include "hal_led.h"
static void hal_ledconfig(void);//外部接口
void hal_LEDInit(void)
{
hal_ledconfig();
}
static void hal_ledconfig(void)
{
GPIO_InitTypeDef GPIOInitStructure;//创建GPIO结构体变量
//用到了GPIOA和GPIOB,打开
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//打开GPIOA的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//打开GPIOB的时钟
//用到什么外设就需要打开对应外设的时钟,不然初始化不会成功
GPIOInitStructure.GPIO_Pin=LED1_Pin;//LED1_Pin是对GPIOA_Pin1的宏定义目的是便于移植
GPIOInitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//这里我们需要控制灯所以将引脚设置成推挽输出模式
GPIOInitStructure.GPIO_Speed=GPIO_Speed_50MHz;//速度一般设置成50MHZ,当然你们可以自己去配置成其他的
GPIO_Init(LED1_PORT,&GPIOInitStructure);//将GPIOA_Pin_1的初始化结构体参数初始化
GPIO_ResetBits(LED1_PORT,LED1_Pin);//关闭灯
GPIOInitStructure.GPIO_Pin=BUZ_Pin;//再给GPIOB_Pin_0配置,BUZZER和LED1的配置相同这边就不重复说明了
GPIOInitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIOInitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(BUZ_PORT,&GPIOInitStructure);
GPIO_ResetBits(BUZ_PORT,BUZ_Pin);
}
//通过该函数来控制灯的亮灭,当然这边形参的类型可以使用bool
void LED1Drive(unsigned char start)//当传入的start>0时都是将灯打开,=0时关闭灯
{
if(start)
{
GPIO_SetBits(GPIOA,GPIO_Pin_1);
}
else
{
GPIO_ResetBits(GPIOA,GPIO_Pin_1);
}
}
//buzzer同LED1相同
void BUZZERDrive(unsigned char start)
{
if(start)
{
GPIO_SetBits(GPIOB,GPIO_Pin_0);
}
else
{
GPIO_ResetBits(GPIOB,GPIO_Pin_0);
}
}
void hal_Turn_led(void)//翻转LED1的引脚电平
{
GPIO_WriteBit(GPIOA,GPIO_Pin_1,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_1)));
}
led.h
#ifndef __HAL_LED_H
#define __HAL_LED_H
#define LED1_PORT GPIOA
#define LED1_Pin GPIO_Pin_1
#define BUZ_PORT GPIOB
#define BUZ_Pin GPIO_Pin_0
void hal_LEDInit(void);
void LED1Drive(unsigned char start);
void BUZZERDrive(unsigned char start);
void hal_Turn_led(void);
#endif
usart.c
#include "stm32f10x.h" // Device header
#include "hal_usart.h"
#include "hal_led.h"
static void hal_USARTConfig(void);//声明
void hal_USARTInit(void)//用初始化函数调用,初始化,留给外部一个接口//在主函数调用
{
hal_USARTConfig();
}
static void hal_USARTConfig(void)//配置函数不让外部改变
{
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);//打开串口1和GPIOA的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//打开复用时钟AFIO
GPIO_InitStructure.GPIO_Pin = USART1_RX_Pin;//配置PA10引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度配置成50MHZ
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //模式配置成浮空模式
GPIO_Init(USART1_RX_PORT, &GPIO_InitStructure);//初始化函数来根据结构体参数来配置GPIO_Pin_10
GPIO_InitStructure.GPIO_Pin = USART1_TX_Pin;//配置PA9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度配置成50MHZ
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//模式配置成复用推挽输出
GPIO_Init(USART1_TX_PORT, &GPIO_InitStructure);//初始化函数来根据结构体参数来配置GPIO_Pin_9
//串口1结构体内含的参数,根据参数来配置串口
USART_InitStructure.USART_BaudRate=115200;//串口1的波特率
USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//流控制,一般不打开,
USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;//模式设置成发送和接收
USART_InitStructure.USART_Parity=USART_Parity_No;//将0 宏定义成USART_Parity_No,代表无校验
USART_InitStructure.USART_StopBits=USART_StopBits_1;//0代表停止位是1位
USART_InitStructure.USART_WordLength=USART_WordLength_8b;//数据长度是8位
USART_Init(USART1,&USART_InitStructure);//将参数设置到串口1
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//使能接收中断
USART_ITConfig(USART1,USART_IT_TXE,DISABLE);//关闭发送中断,发送中断由自己决定当有数据要发送时由程序打开,发送完后需要关闭
USART_Cmd(USART1,ENABLE);//使能串口1
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);//分组,将中断分到0组
NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;//确认中断是串口中断
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//使能中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//子优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;//主优先级
NVIC_Init(&NVIC_InitStructure);//将参数配置到中断中
}
static void hal_DebugSendByte(unsigned char Dat)//串口发送函数static代表仅在该.c文件中调用
{
USART_SendData(USART1, Dat);//将接收到的数据发送出去//库函数
USART_ITConfig(USART1, USART_IT_TXE, ENABLE); //使能发送中断
}
void USART1_IRQHandler(void)//串口1中断服务函数
{
unsigned char dat;
if(USART_GetITStatus(USART1,USART_IT_RXNE) != RESET)//当有数据时
{
dat = USART_ReceiveData(USART1);//将数据给dat
if(dat==0)
{
LED1Drive(0);//关闭灯
hal_DebugSendByte(dat);//将接收到的数据在通过串口发送到串口助手
}
else
{
//接收到的数据>1就是打开灯
LED1Drive(dat);
hal_DebugSendByte(dat);//将接收到的数据在通过串口发送到串口助手
}
USART_ClearITPendingBit(USART1,USART_IT_RXNE);//清除标志位
}
if(USART_GetITStatus(USART1,USART_IT_TXE) != RESET)//发送模式
{
USART_ClearITPendingBit(USART1, USART_IT_TXE);//先清除标志位
USART_ITConfig(USART1, USART_IT_TXE, DISABLE);//发送完成后将关闭发送中断
}
}
usart.h
#ifndef __HAL_USART_H__
#define __HAL_USART_H__
#define USART1_RX_PORT GPIOA
#define USART1_RX_Pin GPIO_Pin_10
#define USART1_TX_PORT GPIOA
#define USART1_TX_Pin GPIO_Pin_9
#define USART2_RX_PORT GPIOA
#define USART2_RX_Pin GPIO_Pin_3
#define USART2_TX_PORT GPIOA
#define USART2_TX_Pin GPIO_Pin_2
#define DEBUG_TXBUFF_SIZE_MAX 400
void hal_USARTInit(void);
#endif
main.c
#include "stm32f10x.h" // Device header
#include "hal_led.h"
#include "hal_usart.h"
int main()
{
hal_LEDInit();
hal_USARTInit();
while(1)
{
}
}
发送时注意,发送是ASCII码值,0对应的是\0,其他字符发送都是>0的数据
示例:
VID20230425103232
需要通过接收到的信息完成其他功能只需要在接收判断中加入想要完成的操作即可
如图: