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
暂无评论