串口中断控制灯的开关

近期脑子有点抽象,想一下估计也有家伙和我一样,所以就分享给抽象的大家如何串口控制LED灯

写的不好,希望大家不要喷我。

1、首先是串口的初始化:

初始化串口1,中断优先级随便设置,反正只有一个函数怕啥。速率2MHZ就够了毕竟公司要求我们还是需要节能的。2M狗狗的。校验位啥的看着设,哎无所谓的。随便写的。

#include "USART.h"
extern uint8_t flag;

void USART_Config_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	USART_InitTypeDef  USART_InitStruct;
	NVIC_InitTypeDef  NVIC_InitStruct;
	//初始化GPIOA_PIN9|10号引脚,USART1,AFIO复用功能
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1|RCC_APB2Periph_AFIO, ENABLE);

	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9 ;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;

	//初始化GPIO引脚
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
	
	GPIO_Init(GPIOA,&GPIO_InitStruct);

	USART_InitStruct.USART_BaudRate = 115200;	//波特率
	USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;	//硬件流控制
	USART_InitStruct.USART_Mode = USART_Mode_Rx|USART_Mode_Tx; //发送接收模式
	USART_InitStruct.USART_StopBits = USART_StopBits_1;//停止位
	USART_InitStruct.USART_Parity = USART_Parity_No;//奇偶校验
	USART_InitStruct.USART_WordLength = USART_WordLength_8b;	//数据位
	//初始化串口
	USART_Init(USART1, &USART_InitStruct);
	
	//配置接受中断源:USART_IT_RXNE
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

	//配置中断优先级NVIC
	NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;	
	NVIC_Init(&NVIC_InitStruct);
	
	USART_ClearFlag(USART1,USART_FLAG_TC|USART_FLAG_TXE);
	//打开串口1
	USART_Cmd(USART1, ENABLE );
	
	
}

2、数据发送函数接受函数

相信大家都是聪明人,都看的懂的,不懂就要去学习咯,我也是哦,不懂就去多学习。

为啥定义要用volatile ?可能我比较乐意吧。毕竟没有优化嘛,直接从内存地址中读数据嘛。

void Send_Msg(uint8_t data)
{
	USART_SendData(USART1,data);//发送信息
	while(SET != USART_GetFlagStatus(USART1,USART_FLAG_TC));//发送标志位获取,知道发送全
}

void Rev_Msg(void)
{	
	if(SET==USART_GetFlagStatus(USART1,USART_FLAG_RXNE)){//接受数据
		USART_ClearFlag(USART1,USART_FLAG_RXNE);//清除标志位置
		USART_SendData(USART1,USART_ReceiveData(USART1));//发送信息到串口助手
	}
}
extern uint8_t flag;//判断是否接受完全的标志位
extern char ptr[50];  //接受数据数组
volatile uint8_t recv_data;
volatile uint32_t strIndex = 0;
void USART1_IRQHandler(void)
{
	
	//中断服务函数
	if(SET == USART_GetFlagStatus(USART1,USART_IT_RXNE))
	{
		//清除标志位
		USART_ClearITPendingBit(USART1,USART_IT_RXNE);//
		recv_data = USART_ReceiveData(USART1);//把接受到的数据放到变量中
		//USART_SendData(USART1,recv_data);//发送信息到串口助手
		
	//	while(SET != USART_GetFlagStatus(USART1,USART_FLAG_TC));				
		if(recv_data =='\n'){
			ptr[strIndex] = '\0'; 
			flag = 1; 
			strIndex = 0;			
		}else {
			ptr[strIndex] = recv_data;
			strIndex++;			
		}
		
	}
				
}

3、printf从定向函数

STM32无法使用printf,因为没有屏幕?没关系,直接将打印的东西从定向到串口就是咯。

上面为啥不要USART_SendData(USART1,recv_data);和while(SET != USART_GetFlagStatus(USART1,USART_FLAG_TC));

可能我比较乐意吧,大家想用也可以用,没关系,相信你自己会出手的。

int fputc(int ch,FILE *f)
{
	USART1->DR=(uint8_t)ch;   //将其强转为char类型数据放入数据寄存器中
	
	while(0==(USART1->SR&(1<<6)));  //循环发送
	USART1->SR &=~(1<<6);
	return ch;
	
}

4、串口的h文件

哎,头文件啥的,简单写一下就是了。

#ifndef __USART_H
#define __USART_H

#include "stm32f10x.h"                  // Device header

void Send_Msg(uint8_t data);
void Rev_Msg(void);
void USART_Config_Init(void);
#include "stdio.h"
#include "string.h"
int fputc(int ch,FILE*f);
#endif

5、LED灯的初始化

这个总不用我写吧。

算了还是写一下吧

void LED_Init(void)
{
	
//打开时钟
	RCC->APB2ENR |=(1<<4);
	// 1》设置GPIOC8模式为通用推挽输出----GPIOC->CRH的第3---0位配置成0010
	GPIOC->CRH  &=~(0xf);
	GPIOC->CRH  |=(1<<1);
	GPIOC->CRL  &=~(0xf);
	GPIOC->CRL  |=(1<<29);
	GPIOC->CRL  |=(1<<25);

	// 2》关灯----GPIOC->ODR的第8位配置为1
	GPIOC->ODR  |=(1<<8);
	GPIOC->ODR  |=(1<<7);
	GPIOC->ODR  |=(1<<6);

}

LED头文件

好人做到,送佛送到西,一路写下去咯

#ifndef __LED_H
#define __LED_H

#include "stm32f10x.h"                  // Device header

#define LED_ON  GPIO_ResetBits(GPIOC, GPIO_Pin_8|GPIO_Pin_7|GPIO_Pin_6)
#define LED_OFF GPIO_SetBits(GPIOC, GPIO_Pin_8|GPIO_Pin_7|GPIO_Pin_6)
void LED_Init(void);
#endif

main函数;

就这样了,直接ok了

#include "stm32f10x.h"                  // Device header
#include "USART.h"
#include "LED.h"
uint8_t flag;
char ptr[20];
int main()
{	
	LED_Init();
	
	//中断管理方式
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
	USART_Config_Init();
	
	while(1){
		
		
		if(flag){
			
			printf("%s\n",ptr);
			if(strncmp(ptr,"open",4)==0){
		
					LED_ON;
					flag = 0;
				}
			if(strncmp(ptr,"close",5)==0){
				
					LED_OFF;
					flag = 0;
				}		
		}		
}
			
}

串口结果:


我反正点亮了,你们我就不管了。下班咯

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以帮你解答这个问题。首先,你需要准备一个C51单片机和一个串口模块,然后按照以下步骤进行操作: 1.连接串口模块到C51单片机,并将串口模块的TXD引脚连接到单片机的P3.1引脚,将RXD引脚连接到单片机的P3.0引脚。 2.编写C语言程序,在程序中初始化串口模块和流水控制引脚。 3.使用串口模块接收PC端发送的控制指令,根据指令控制流水开关状态。 下面是一个简单的C语言程序示例,实现通过串口控制流水: ```c #include <reg52.h> // 定义串口模块使用的波特率 #define BAUDRATE 9600 // 初始化串口模块 void init_uart() { // 将波特率设为BAUDRATE TMOD |= 0x20; TH1 = 0xFD; TL1 = 0xFD; TR1 = 1; // 允许串口中断 ES = 1; EA = 1; } // 串口中断处理函数 void uart_isr() interrupt 4 { // 判断是否接收到了数据 if(RI) { // 读取接收到的数据 char c = SBUF; // 根据接收到的指令控制流水 switch(c) { case '0': P1 = 0xFF; break; case '1': P1 = 0xFE; break; case '2': P1 = 0xFC; break; case '3': P1 = 0xF8; break; case '4': P1 = 0xF0; break; case '5': P1 = 0xE0; break; case '6': P1 = 0xC0; break; case '7': P1 = 0x80; break; default: break; } // 清除接收中断标志位 RI = 0; } } // 主函数 void main() { // 初始化串口模块 init_uart(); // 初始化流水控制引脚 P1 = 0xFF; // 循环等待指令 while(1); } ``` 在上述程序中,通过串口接收PC端发送的指令,并根据指令控制P1口输出,从而控制流水开关状态。指令格式为一个字符,取值范围为0~7,表示流水的不同状态。例如,当接收到字符'0'时,流水关闭;当接收到字符'1'时,流水从左往右移动一个,以此类推。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值