STM32串口控制LED灯的亮灭

STM32中的串口控制LED灯的亮灭,分为两种方式,一种是直接发送数字0和1来控制灯的亮灭,另一种是通过发送字符串来控制。

我所使用的开发板主控芯片是STM32F401RET6,主频84MHz,

首先要进行串口的初始化:

/*
函数功能:串口的初始化
函数名:Usart_Init
返回值:无
参数:u32 brr
备注:
USART1_TXD->PA9
USART1_RXD->PA10

*/
void Usart_Init(u32 brr)
{
	float div;
	u16 div_m;
	u16 div_f;
	//1.打开GPIOA,USART1的时钟
	RCC->AHB1ENR	|= (1<<0);
  RCC->APB2ENR	|= (1<<4);
	
	//2.把PA9配置为复用推挽输出,把PA10配置为浮空输入模式
	GPIOA->MODER &= ~(3<<18);//清零
	GPIOA->MODER |= (2<<18);//复用功能模式
	GPIOA->OTYPER &= ~(1<<9);//输出推挽
	GPIOA->OSPEEDR &= ~(3<<18);//清零
	GPIOA->OSPEEDR |=(3<<18);//输出高速
	
	GPIOA->MODER &= ~(3<<20);//输入模式
	GPIOA->MODER |= (2<<20);//复用功能
	
	GPIOA->PUPDR &= ~(3<<20);//无上下拉
	
	//3.把USART1映射复用到PA9,PA10上
	GPIOA->AFR[1] |=(0x7<<4);//USART1映射到PA9
	GPIOA->AFR[1] |=(0x7<<8);//USART1映射到PA10
	
	//4.配置串口:
	1.打开接收器和发送器
	USART1->CR1 |= (3<<2);
	
	2.禁止奇偶校验
	USART1->CR1 &= ~(1<<10);
	3.选择字长
	USART1->CR1 &= ~(1<<12);
	4.选择过采样
	USART1->CR1 &= ~(1<<15);
	5.配置停止位
	USART1->CR2 &= ~(3<<12);
	
	6.计算波特率寄存器
	div = 84000000.0/16/brr;
	div_m = (int)div;
	div_f = (div-div_m)*16+0.5f;
	USART1->BRR |= div_f|(div_m<<4);
	7.打开USART1模块使能
	USART1->CR1 |= (1<<13);
	
}

由于用到了printf函数,需要添加以下代码段,取消半主机状态:

/************************printf支持函数****************************/
#pragma import(__use_no_semihosting_swi) //取消半主机状态

struct __FILE { int handle; /* Add whatever you need here */ };
FILE __stdout;

int fputc(int ch, FILE *f) {
	while((USART1->SR &(0X01<<7))==0){};
		USART1->DR=ch;
  return (ch);
}
int ferror(FILE *f) {
  /* Your implementation of ferror */
  return EOF;
}

void _ttywrch(int ch) {
  while((USART1->SR &(0X01<<7))==0);
		USART1->DR=ch;
}

void _sys_exit(int return_code) {
label:  goto label;  /* endless loop */
}

方式一:

/*
函数名:Usart_Cont1
函数功能:串口的控制方式
返回值:无
形参:无
备注:
发送31,使LED3亮;发送30,使LED3灭;
发送41,使LED4亮;发送40,使LED4灭;

*/

void Usart_Cont1(void)
{
	u8 value[2];
	u8 i;
	for(i=0;i<2;i++)
	{
		while(!(USART1->SR & (1<<5))){};//等待数据接收完成
		value[i]=USART1->DR;
		
	}
	switch(value[0])
	{
		case '3':
			if(value[1]=='1')
			{
				LED3_ON;
			}
			else if(value[1]=='0')
			{
				LED3_OFF;
			}
			break;
		case '4':
			if(value[1]=='1')
			{
				LED4_ON;
			}
			else if(value[1]=='0')
			{
				LED4_OFF;
			}		
			break;
	}
}

方式二:

/*
函数名:Usart_Cont2
函数功能:串口的控制方式
返回值:无
形参:无
备注:
发送LED3_ON,使LED3亮;发送LED3_OF,使LED3灭;
发送LED4_ON,使LED4亮;发送LED4_OF,使LED4灭;

*/


void Usart_Cont2(void)
{
	u8 value1[8]={0};
	u8 i;
	for(i=0;i<7;i++)
	{
		while(!(USART1->SR & (1<<5))){};//等待数据接收完成
		value1[i]=USART1->DR;
	}
	value1[7]='\0';
	if(!(strcmp((const char *)value1,"LED3_ON")))
	{
		LED3_ON;
	}
	else if(!(strcmp((const char *)value1,"LED3_OF")))
	{
		LED3_OFF;
	}
	else if(!(strcmp((const char *)value1,"LED4_ON")))
	{
		LED4_ON;
	}	
	else if(!(strcmp((const char *)value1,"LED4_OF")))
	{
		LED4_OFF;
	}
}

调试时要注意的一些问题:

(1)串口调试助手XCOM V2.6部分字符会乱码,需要使用低版本的串口调试助手,如XCOM V1.4

(2)使用多条发送时,需要取消勾选“发送新行”,将间隔改为1ms,使用单条发送无此问题

(3)STM32串口的调试需要明确芯片的主频,选择正确的波特率,否则会出现乱码

(4)有些开发板还需要将拨码开关拨上才能进行串口调试实验,如我之前使用的主控芯片为STM32F411CEU6的智能手环开发板

完整工程源代码:https://download.csdn.net/download/qq_44678890/76737688

版权声明:本文为CSDN博主「缺憾,残影过后」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_44678890/article/details/122589754

STM32中的串口控制LED灯的亮灭,分为两种方式,一种是直接发送数字0和1来控制灯的亮灭,另一种是通过发送字符串来控制。

我所使用的开发板主控芯片是STM32F401RET6,主频84MHz,

首先要进行串口的初始化:

/*
函数功能:串口的初始化
函数名:Usart_Init
返回值:无
参数:u32 brr
备注:
USART1_TXD->PA9
USART1_RXD->PA10

*/
void Usart_Init(u32 brr)
{
	float div;
	u16 div_m;
	u16 div_f;
	//1.打开GPIOA,USART1的时钟
	RCC->AHB1ENR	|= (1<<0);
  RCC->APB2ENR	|= (1<<4);
	
	//2.把PA9配置为复用推挽输出,把PA10配置为浮空输入模式
	GPIOA->MODER &= ~(3<<18);//清零
	GPIOA->MODER |= (2<<18);//复用功能模式
	GPIOA->OTYPER &= ~(1<<9);//输出推挽
	GPIOA->OSPEEDR &= ~(3<<18);//清零
	GPIOA->OSPEEDR |=(3<<18);//输出高速
	
	GPIOA->MODER &= ~(3<<20);//输入模式
	GPIOA->MODER |= (2<<20);//复用功能
	
	GPIOA->PUPDR &= ~(3<<20);//无上下拉
	
	//3.把USART1映射复用到PA9,PA10上
	GPIOA->AFR[1] |=(0x7<<4);//USART1映射到PA9
	GPIOA->AFR[1] |=(0x7<<8);//USART1映射到PA10
	
	//4.配置串口:
	1.打开接收器和发送器
	USART1->CR1 |= (3<<2);
	
	2.禁止奇偶校验
	USART1->CR1 &= ~(1<<10);
	3.选择字长
	USART1->CR1 &= ~(1<<12);
	4.选择过采样
	USART1->CR1 &= ~(1<<15);
	5.配置停止位
	USART1->CR2 &= ~(3<<12);
	
	6.计算波特率寄存器
	div = 84000000.0/16/brr;
	div_m = (int)div;
	div_f = (div-div_m)*16+0.5f;
	USART1->BRR |= div_f|(div_m<<4);
	7.打开USART1模块使能
	USART1->CR1 |= (1<<13);
	
}

由于用到了printf函数,需要添加以下代码段,取消半主机状态:

/************************printf支持函数****************************/
#pragma import(__use_no_semihosting_swi) //取消半主机状态

struct __FILE { int handle; /* Add whatever you need here */ };
FILE __stdout;

int fputc(int ch, FILE *f) {
	while((USART1->SR &(0X01<<7))==0){};
		USART1->DR=ch;
  return (ch);
}
int ferror(FILE *f) {
  /* Your implementation of ferror */
  return EOF;
}

void _ttywrch(int ch) {
  while((USART1->SR &(0X01<<7))==0);
		USART1->DR=ch;
}

void _sys_exit(int return_code) {
label:  goto label;  /* endless loop */
}

方式一:

/*
函数名:Usart_Cont1
函数功能:串口的控制方式
返回值:无
形参:无
备注:
发送31,使LED3亮;发送30,使LED3灭;
发送41,使LED4亮;发送40,使LED4灭;

*/

void Usart_Cont1(void)
{
	u8 value[2];
	u8 i;
	for(i=0;i<2;i++)
	{
		while(!(USART1->SR & (1<<5))){};//等待数据接收完成
		value[i]=USART1->DR;
		
	}
	switch(value[0])
	{
		case '3':
			if(value[1]=='1')
			{
				LED3_ON;
			}
			else if(value[1]=='0')
			{
				LED3_OFF;
			}
			break;
		case '4':
			if(value[1]=='1')
			{
				LED4_ON;
			}
			else if(value[1]=='0')
			{
				LED4_OFF;
			}		
			break;
	}
}

方式二:

/*
函数名:Usart_Cont2
函数功能:串口的控制方式
返回值:无
形参:无
备注:
发送LED3_ON,使LED3亮;发送LED3_OF,使LED3灭;
发送LED4_ON,使LED4亮;发送LED4_OF,使LED4灭;

*/


void Usart_Cont2(void)
{
	u8 value1[8]={0};
	u8 i;
	for(i=0;i<7;i++)
	{
		while(!(USART1->SR & (1<<5))){};//等待数据接收完成
		value1[i]=USART1->DR;
	}
	value1[7]='\0';
	if(!(strcmp((const char *)value1,"LED3_ON")))
	{
		LED3_ON;
	}
	else if(!(strcmp((const char *)value1,"LED3_OF")))
	{
		LED3_OFF;
	}
	else if(!(strcmp((const char *)value1,"LED4_ON")))
	{
		LED4_ON;
	}	
	else if(!(strcmp((const char *)value1,"LED4_OF")))
	{
		LED4_OFF;
	}
}

调试时要注意的一些问题:

(1)串口调试助手XCOM V2.6部分字符会乱码,需要使用低版本的串口调试助手,如XCOM V1.4

(2)使用多条发送时,需要取消勾选“发送新行”,将间隔改为1ms,使用单条发送无此问题

(3)STM32串口的调试需要明确芯片的主频,选择正确的波特率,否则会出现乱码

(4)有些开发板还需要将拨码开关拨上才能进行串口调试实验,如我之前使用的主控芯片为STM32F411CEU6的智能手环开发板

完整工程源代码:https://download.csdn.net/download/qq_44678890/76737688

版权声明:本文为CSDN博主「缺憾,残影过后」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_44678890/article/details/122589754

生成海报
点赞 0

缺憾,残影过后

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

STM32 QSPI双闪存操作

STM32 QSPI双闪存操作 使用CubeMX或者CubeIDE生成框架 使用野火的开发板,MCU型号为stm32h750/743,他们家核心板上使用了QSPI挂了2片FLASH,型号为W25Q2

AD原理图设计与Clion源码工具学习

一、AD绘制电路原理图 1.准备工作 下载Altium Designer,具体安装步骤以及百度网盘分享参考:Altium Designer2018下载安装及基本使用 STM32F103C8T6元件库&#xff1a

GPIO使用教程(学习笔记)

前言 本文主要讲解如何驱动GPIO外设的相应寄存器搭建GPIO的工作环境,牵及的各种代码本人都会逐条进行讲解。主控芯片采用STM32F103C8T6,外设采用普通的LED发光二极管。驱动LED发光二极管显示GPIO