STM32单片机红外遥控

news2024/11/15 12:55:43

红外遥控接口电路

STM32单片机红外遥控程序源代码

#include "sys.h"

#define LED_RED PBout(12) //红色发光二极管控制管脚初始化PB12

#define LED_GREEN PBout(13) //绿色发光二极管控制管脚初始化PB13

#define LED_YELLOW PBout(14) //黄色发光二极管控制管脚初始化PB14

#define LED_BLUE PBout(15) //蓝色发光二极管控制管脚初始化PB15

#define BEEP PBout(5) //蜂鸣器端口定义PB5

#define RDATA PAin(1) //红外数据输入脚

//红外遥控识别码(ID),每款遥控器的该值基本都不一样,但也有一样的

//我们选用的遥控器识别码为0

#define REMOTE_ID 0

static u8 fac_us=0; //us延时倍乘数

static u16 fac_ms=0; //ms延时倍乘数

void delay_init(u8 SYSCLK);

void delay_ms(u16 nms);

void delay_us(u32 nus);

void Led_Init(void); //发光二极管控制管脚初始化

void Red_Led_Light(void); //点亮红色发光二极管

void Green_Led_Light(void); //点亮绿色发光二极管

void Yellow_Led_Light(void); //点亮黄色发光二极管

void Blue_Led_Light(void); //点亮蓝色发光二极管

void Red_Led_Goout(void); //熄灭红色发光二极管

void Green_Led_Goout(void); //熄灭绿色发光二极管

void Yellow_Led_Goout(void); //熄灭黄色发光二极管

void Blue_Led_Goout(void); //熄灭蓝色发光二极管

void Beep_Init(void);

void Beep_Tweet(void);

void Beep_Silent(void);

extern u8 Remote_Cnt; //按键次数,此次按下键的次数

extern u8 Remote_Rdy; //红外接收到数据

extern u32 Remote_Odr; //命令暂存处

u32 Remote_Odr=0; //命令暂存处

u8 Remote_Cnt=0; //按键次数,此次按下键的次数

u8 Remote_Rdy=0; //红外接收到数据

void Remote_Init(void); //红外传感器接收头引脚初始化

u8 Remote_Process(void); //红外接收到数据处理

u8 Pulse_Width_Check(void); //检查脉宽

extern u8 USART_RX_BUF[64]; //接收缓冲,最大63个字节.末字节为换行符

extern u8 USART_RX_STA; //接收状态标记

//如果想串口中断接收,请不要注释以下宏定义

//#define EN_USART1_RX //使能串口1接收

void uart_init(u32 pclk2,u32 bound);

/*************************************************************

开发板上电后,用红外遥控器对着开发板上的红外接收头。

按下遥控器上的按键0,开发板通过串口(程序下载的串口)发送数值0;

按下遥控器上的按键1,开发板通过串口(程序下载的串口)发送数值1;

按下遥控器上的按键2,开发板通过串口(程序下载的串口)发送数值2;

按下遥控器上的按键3,开发板通过串口(程序下载的串口)发送数值3;

按下遥控器上的按键4,开发板通过串口(程序下载的串口)发送数值4;

按下遥控器上的按键5,开发板通过串口(程序下载的串口)发送数值5;

按下遥控器上的按键6,开发板通过串口(程序下载的串口)发送数值6;

按下遥控器上的按键7,开发板通过串口(程序下载的串口)发送数值7;

按下遥控器上的按键8,开发板通过串口(程序下载的串口)发送数值8;

按下遥控器上的按键9,开发板通过串口(程序下载的串口)发送数值9;

串口助手设置:波特率9600 数据位:8 停止位:1 HEX显示

*************************************************************/

void delay_init(u8 SYSCLK)

{

SysTick->CTRL&=0xfffffffb; //bit2清空,选择外部时钟 HCLK/8

fac_us=SYSCLK/8;

fac_ms=(u16)fac_us*1000;

}

void delay_ms(u16 nms)

{

u32 temp;

SysTick->LOAD=(u32)nms*fac_ms; //时间加载(SysTick->LOAD为24bit)

SysTick->VAL =0x00; //清空计数器

SysTick->CTRL=0x01 ; //开始倒数

do{temp=SysTick->CTRL;}

while(temp&0x01&&!(temp&(1<<16))); //等待时间到达

SysTick->CTRL=0x00; //关闭计数器

SysTick->VAL =0X00; //清空计数器

}

void delay_us(u32 nus)

{

u32 temp;

SysTick->LOAD=nus*fac_us; //时间加载

SysTick->VAL=0x00; //清空计数器

SysTick->CTRL=0x01 ; //开始倒数

do{temp=SysTick->CTRL;}

while(temp&0x01&&!(temp&(1<<16))); //等待时间到达

SysTick->CTRL=0x00; //关闭计数器

SysTick->VAL =0X00; //清空计数器

}

void Led_Init(void)

{

RCC->APB2ENR|=1<<3; //使能PORTB接口时钟

GPIOB->CRH&=0XFFF0FFFF;

GPIOB->CRH|=0X00030000; //PB12推挽输出

GPIOB->ODR|=1<<12; //PB12输出高电平

GPIOB->CRH&=0XFF0FFFFF;

GPIOB->CRH|=0X00300000; //PB13推挽输出

GPIOB->ODR|=1<<13; //PB13输出高电平

GPIOB->CRH&=0XF0FFFFFF;

GPIOB->CRH|=0X03000000; //PB14推挽输出

GPIOB->ODR|=1<<14; //PB14输出高电平

GPIOB->CRH&=0X0FFFFFFF;

GPIOB->CRH|=0X30000000; //PB15推挽输出

GPIOB->ODR|=1<<15; //PB15输出高电平

}

void Red_Led_Light(void){LED_RED=0;}

void Red_Led_Goout(void){LED_RED=1;}

voidGreen_Led_Light(void){LED_GREEN=0;}

voidGreen_Led_Goout(void){LED_GREEN=1;}

void Yellow_Led_Light(void){LED_YELLOW=0;}

voidYellow_Led_Goout(void){LED_YELLOW=1;}

void Blue_Led_Light(void){LED_BLUE=0;}

void Blue_Led_Goout(void){LED_BLUE=1;}

void Beep_Init(void)

{

RCC->APB2ENR|=1<<3; //使能PORTB时钟

GPIOB->CRL&=0XFF0FFFFF;

GPIOB->CRL|=0X00300000; //PB5推挽输出

GPIOB->ODR|=1<<5; //PB5输出高

}

void Beep_Tweet(void){BEEP=0;}

void Beep_Silent(void){BEEP=1;}

void Remote_Init(void)

{

RCC->APB2ENR|=1<<2; //PA时钟使能

GPIOA->CRL&=0XFFFFFF0F;

GPIOA->CRL|=0X00000080; //PA1输入

GPIOA->ODR|=1<<1; //PA.1上拉

Ex_NVIC_Config(GPIO_A,1,FTIR); //将line1映射到PA.1,下降沿触发.

MY_NVIC_Init(2,1,EXTI1_IRQChannel,2);

}

u8 Pulse_Width_Check(void)

{

u8 t=0;

while(RDATA)

{t++;delay_us(20);if(t==250)return t;} //超时溢出

return t;

}

void EXTI1_IRQHandler(void)

{

u8 res=0;u8 OK=0;u8 RODATA=0;

while(1)

{

if(RDATA) //有高脉冲出现

{

res=Pulse_Width_Check(); //获得此次高脉冲宽度

if(res==250)break; //非有用信号

if(res>=200&&res<250)OK=1; //获得前导位(4.5ms)

else if(res>=85&&res<200) //按键次数加一(2ms)

{

Remote_Rdy=1; //接受到数据

Remote_Cnt++; //按键次数增加

break;

}

else if(res>=50&&res<85)RODATA=1;//1.5ms

else if(res>=10&&res<50)RODATA=0;//500us

if(OK)

{

Remote_Odr<<=1;

Remote_Odr+=RODATA;

Remote_Cnt=0; //按键次数清零

}

}

}

EXTI->PR=1<<1; //清除中断标志位

}

u8 Remote_Process(void)

{

u8 t1,t2;

t1=Remote_Odr>>24; //得到地址码

t2=(Remote_Odr>>16)&0xff; //得到地址反码

Remote_Rdy=0; //清除标记

if(t1==(u8)~t2&&t1==REMOTE_ID) //检验遥控识别码(ID)及地址

{

t1=Remote_Odr>>8;

t2=Remote_Odr;

if(t1==(u8)~t2)return t1; //处理键值

}

return 0;

}

void uart_init(u32 pclk2,u32 bound)

{

float temp;

u16 mantissa;

u16 fraction;

temp=(float)(pclk2*1000000)/(bound*16); //得到USARTDIV

mantissa=temp; //得到整数部分

fraction=(temp-mantissa)*16; //得到小数部分

mantissa<<=4;

mantissa+=fraction;

RCC->APB2ENR|=1<<2; //使能PORTA口时钟

RCC->APB2ENR|=1<<14; //使能串口时钟

GPIOA->CRH&=0XFFFFF00F;

GPIOA->CRH|=0X000008B0; //IO状态设置

RCC->APB2RSTR|=1<<14; //复位串口1

RCC->APB2RSTR&=~(1<<14); //停止复位

//波特率设置

USART1->BRR=mantissa; //波特率设置

USART1->CR1|=0X200C; //1位停止,无校验位.

#ifdef EN_USART1_RX //如果使能了接收

//使能接收中断

USART1->CR1|=1<<8; //PE中断使能

USART1->CR1|=1<<5; //接收缓冲区非空中断使能

MY_NVIC_Init(3,3,USART1_IRQChannel,2); //组2,最低优先级

#endif

}

int main(void)

{

u8 key;u8 t;

Stm32_Clock_Init(9); //时钟初始化

delay_init(72); //延时

uart_init(72,9600); //串口初始化

Led_Init(); //发光二极管控制管脚初始化

Remote_Init(); //红外遥控控制初始化

Beep_Init(); //蜂鸣器控制管脚初始化

while(1)

{

if(Remote_Rdy) //如果接收到红外遥控信号

{

key = Remote_Process(); //获取按键值

Beep_Tweet(); //蜂鸣器响

delay_ms(50); //延迟一段时间

Beep_Silent(); //蜂鸣器不响

switch(key) //判断键值

{

case 0x68: //如果键值是0x68

{USART1->DR=0x00;while((USART1->SR&0X40)==0);}break;//通过串口发送0x00

case 0x30: //如果键值是0x30

{USART1->DR=0x01;while((USART1->SR&0X40)==0);}break;//通过串口发送0x01

case 0x18: //如果键值是0x18

{USART1->DR=0x02;while((USART1->SR&0X40)==0);}break;//通过串口发送0x02

case 0x7A: //如果键值是0x7A

{USART1->DR=0x03;while((USART1->SR&0X40)==0);}break;//通过串口发送0x03

case 0x10: //如果键值是0x10

{USART1->DR=0x04;while((USART1->SR&0X40)==0);}break;//通过串口发送0x04

case 0x38: //如果键值是0x38

{USART1->DR=0x05;while((USART1->SR&0X40)==0);}break;//通过串口发送0x05

case 0x5A: //如果键值是0x5A

{USART1->DR=0x06;while((USART1->SR&0X40)==0);}break;//通过串口发送0x06

case 0x42: //如果键值是0x42

{USART1->DR=0x07;while((USART1->SR&0X40)==0);}break;//通过串口发送0x07

case 0x4A: //如果键值是0x4A

{USART1->DR=0x08;while((USART1->SR&0X40)==0);}break;//通过串口发送0x08

case 0x52: //如果键值是0x52

{USART1->DR=0x09;while((USART1->SR&0X40)==0);}break;//通过串口发送0x09

}

}

else{delay_ms(2);}

t++;

if(t==200)

{t=0;LED_RED = !LED_RED;}

}

}

void USART1_IRQHandler(void)

{

u8 res;

if(USART1->SR&(1<<5)) //接收到数据

{

res=USART1->DR;

if((USART_RX_STA&0x80)==0) //接收未完成

{

if(USART_RX_STA&0x40) //接收到了0x0d

{

if(res!=0x0a)USART_RX_STA=0; //接收错误,重新开始

else USART_RX_STA|=0x80; //接收完成了

}

else //还没收到0X0D

{

if(res==0x0d)USART_RX_STA|=0x40;

else

{

USART_RX_BUF[USART_RX_STA&0X3F]=res;

USART_RX_STA++;

if(USART_RX_STA>63)USART_RX_STA=0;//接收数据错误,重新开始接收

}

}

}

}

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/341869.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

反射,枚举,lambda表达式

目录 1、反射 1.1 基本概念 1.2 反射相关的类 1.3 创建 Class 对象 1.4 反射的使用 1.4.1 通过反射创建对象&#xff1a; 1.4.2 获取私有的构造方法 1.4.3 获取私有的成员变量 1.4.4 获取私有的方法 1.5 总结 2、枚举 2.1 认识枚举 2.2 使用枚举 2.3 枚举与反射…

第4章 流程控制-if-else,Switch,For循环(循环守卫,循环步长,倒叙打印),While循环,多重循环...

第 4 章 流程控制-if-else,Switch,For循环(循环守卫&#xff0c;循环步长&#xff0c;倒叙打印)&#xff0c;While循环&#xff0c;多重循环 4.1 分支控制 if-else 让程序有选择的的执行&#xff0c;分支控制有三种&#xff1a;单分支、双分支、多分支 4.1.1 单分支 1)基本语法…

Leetcode-每日一题1234. 替换子串得到平衡字符串(滑动窗口 + 哈希表)

题目链接&#xff1a;https://leetcode.cn/problems/replace-the-substring-for-balanced-string/description/ 思路 题目意思 这题意思是一个只含有[Q, W, E, R] 四个字符的字符串s且长度一定是 4的倍数&#xff0c; 需要你通过替换子串&#xff0c;使他变成一个「平衡字符…

【C++设计模式】学习笔记(6):Bridge 桥模式

目录 简介动机(Motivation)模式定义结构(Structure)要点总结笔记结语简介 Hello! 非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出~ ଘ(੭ˊᵕˋ)੭ 昵称:海轰 标签:程序猿|C++选手|学生 简介:因C语言结识编程,随后转入计算机专业,获得过国家奖学金…

【C++设计模式】学习笔记(2):模式分类与模版方法 Template Method

目录 简介模式分类GOF-23 模式分类从封装变化角度对模式分类重构获得模式 Refactoring to Patterns重构关键技法“组件协作”模式Template Method 模式动机(Motivation)结构化软件设计流程面向对象软件设计流程早绑定与晚绑定模式的定义结构(Structure)要点总结结语简介 He…

Unity(一)--通过简单例子了解属性、脚本等基础操作

目录新建工程保存视图创建游戏对象调整场景视图角度添加物理运动组件更换材质更改颜色添加脚本点击向上跳跃变色旋转UGUI的使用修改文字内容新建工程 ps:最好不使用中文文件路径及名称&#xff0c;可能会报错。 保存视图 进工程后&#xff0c;此时只有空文件夹&#xff0c;可…

《痞子衡嵌入式半月刊》 第 71 期

痞子衡嵌入式半月刊&#xff1a; 第 71 期 这里分享嵌入式领域有用有趣的项目/工具以及一些热点新闻&#xff0c;农历年分二十四节气&#xff0c;希望在每个交节之日准时发布一期。 本期刊是开源项目(GitHub: JayHeng/pzh-mcu-bi-weekly)&#xff0c;欢迎提交 issue&#xff0c…

新手做跨境电商,选对平台很重要

据数据统计&#xff0c;我国跨境电商早在2013年&#xff0c;发展态势就十分迅猛&#xff0c;交易规模达到2.7万亿元&#xff1b;而到2015年&#xff0c;仅仅两年时间&#xff0c;交易规模就突破到5万亿元&#xff1b;再过两年&#xff0c;2017年跨境电商交易规模增长到7.6万亿元…

okcc呼叫中心怎样搭建?

随着企业对服务逐渐重视&#xff0c;开始意识到呼叫中心作为客户服务水平和沟通效率的基本平台&#xff0c;并且有越来越多的企业开始利用呼叫中心外呼方式销售自己的产品。在此背景下&#xff0c;很多企业&#xff0c;无论规模大小&#xff0c;都有建立自己呼叫中心的想法。 …

docker的资源控制管理——Cgroups

引言&#xff1a;docker 使用cgrqup控制资源&#xff0c;K8S 里面也有limit&#xff08;使用上限&#xff09;docker通过cgroup来控制容器使用的资源配额&#xff0c;包括CPU、内存、磁盘三大方面&#xff0c;基本覆盖了常见的资源配额和使用量控制。Cgroup 是 Control group 的…

Jboss EAP 7.4.8配置jacoco 端口无法开启 启动报错

项目场景&#xff1a; servers: Jboss EAP 7.4.8 JDK: JDK17 jacoco: 测试jacoco-0.7.9 jacoco-0.8.5 jacoco-0.8.8 问题描述 问题1: Jboss 启动 VM arguments追加, 如下启动参数&#xff1a; -javaagent:F:\CoverageReport\jacoco-0.7.9\lib\jacocoagent.jarincludes*,o…

别具一格,原创唯美浪漫情人节表白专辑,(复制就可用)(html5,css3,svg)表白爱心代码(1)

别具一格&#xff0c;原创唯美浪漫情人节表白专辑&#xff0c; (复制就可用)&#xff08;html5,css3,svg)表白爱心代码(1) 一、 前言 回眸之间&#xff0c;丰盈了岁月&#xff0c;涟漪了思绪&#xff0c;轻轻落笔&#xff0c;不写伤痕&#xff0c;不写仇怨&#xff0c;只写岁月…

反光板导航SLAM(三)反光柱导航开发与实验

在上一章中简单了解了VEnus算法对于反光柱导航的基本思路。其主要分为了高反点提取、高反点聚类查找中心、高反点与已知反光柱位姿匹配以及调用ceres库进行位姿优化等步骤。然后在这个算法的基础上&#xff0c;再进行一定的开发达到一个比较稳定且可视化的版本。 使用&#xff…

json对象和formData相互转换

前言 大家都知道&#xff0c;前端在和后台进行交互联调时&#xff0c;肯定避免不了要传递参数&#xff0c;一般情况下&#xff0c;params 在 get 请求中使用&#xff0c;而 post 请求下&#xff0c;我们有两种常见的传参方式&#xff1a; JSON 对象格式和 formData 格式&#x…

《MySQL学习》 索引 下 覆盖索引,MRR,联合索引

一. 覆盖索引 有一张表T1&#xff0c;它的建表语句如下 mysql> create table T1 ( ID int primary key, k int NOT NULL DEFAULT 0, s varchar(16) NOT NULL DEFAULT , index k(k)) engineInnoDB;insert into T1 values(100,1, aa),(200,2,bb),(300,3,cc),(500,5,ee),(60…

为什么子进程要继承处理器亲缘性?

请先考虑一个典型的程序为什么需要启动一个子进程。(当然资源管理器不算一个典型的程序) 这是因为手头的任务被分解为子任务&#xff0c;无论出于何种原因&#xff0c;这些子任务都被放入子流程中。例如&#xff0c;在实现多次遍历型编译器/链接器时&#xff0c;其中每次遍历都…

虹科新品 | 万兆车载以太网媒体转换器-实现更加快捷、高效的连接

多千兆车载以太网 媒体转换器 —— Technica Engineering —— 2.5/5/10GBASE-T1多千兆 Media Converter Media Converter 是一种硬件设备&#xff0c;可在汽车以太网连接&#xff08;100BASE-T1 或 1000BASE-T1&#xff09;和任何具有带 RJ-45 连接器的标准以太网网络接口卡 …

canal同步mysql数据到kafka, kafka消费存入clickhouse

环境win mysql5.7 apache-zookeeper-3.5.9-bin kafka_2.11-1.1.1 canal.deployer-1.1.7-SNAPSHOT 如果不想看步骤可以直接下载我打包好的文件&#xff0c;修改相关数据库配置就行 https://download.csdn.net/download/weixin_38738049/87441074?spm1001.2014.3001.55031新增m…

pytorch 实现情感分类问题

1、词表映射无论是深度学习还是传统的统计机器学习方法处理自然语言&#xff0c;都需要先将输入的语言符号&#xff08;通常为标记Token&#xff09;&#xff0c;映射为大于等于0、小于词表大小的整数&#xff0c;该整数也被称作一个标记的索引值或下标。vocab类实现标记和索引…

C语言(按位运算符和位移运算符)

目录 ​编辑 一.按位运算符 1.二进制反码或按位取反&#xff1a;~ 2.按位与&#xff1a;& 3.按位或&#xff1a;| 4.按位异或&#xff1a;^ 二.位移运算符 1.左移&#xff1a; << 2.右移&#xff1a; >> 一.按位运算符 C有四个按位逻辑运算符都用于整…