STC8G1K08A使用PCA模块红外遥控发射案例

概要

STC8G1K08A使用PCA模块红外遥控发射案例,使用PCA模块产生38khz稳定信号,按照NEC协议,控制38khz信号的开关,从而达到红外发送数据的目的。

技术名词解释

  • NEC协议

 上图已经是解码过的了,控制信号就应像上面这个这样,然后低电平时输出的就是38khz的信号。

所以我们的任务就是产生一个上述控制信号和一个38khz信号接到下面电路的两个三极管(s8550)上就行!

  • 电路图

由于pca模块的频率并不是随心所欲设置,所以会在38khz附近,但通过接收头手册可知,这个频率在一定范围内都是可行的(如下图所示)

技术细节

下面我们直接用代码来展示整个过程:

  • main.c
#include <STC8G.H>
#include "Timer0.h"
#include "Key.h"
#include "Infr.h"

//注:本案例使用了stc8g1k0a的CCAPM2的P54口作为38khz信号
//通过P54的38khz和P55的开关信号产生NEC协议的相关时序
//所以必须使用相关的电路配合使用,
//如案例的两个pnp型三极管控制红外发射管

unsigned char temp,keynum;//按键变量
	

//按下四个按键发送不同的数据
void Key_Scan(void)
{
	temp=Key();
	if(temp)
	{
		keynum=temp;
		switch(keynum)
		{
			case 1:
			Send_Byte(0x00,0x55);
			keynum=0;
			break;
			
			case 2:
			Send_Byte(0x00,0x66);
			keynum=0;
			break;	
			case 3:
			Send_Byte(0x00,0x77);
			keynum=0;
			break;	
			case 4:
			Send_Byte(0x00,0x88);
			keynum=0;
			break;	
		}
	}
}

void main(void)
{	
	
	P3M0 = 0x00; // 将P3配置为准双向口
	P3M1 = 0x00;
	
	P5M0 = 0xff; // 将P5口配置为推挽输出
	P5M1 = 0x00;

	/*********配置pca进而产生一个38khz左右信号***************/
	CCON=0x00;//停止PCA计数
	CMOD=0x04;//PCA计数脉冲设为定时器0的溢出脉冲
	CL= 0x00;
	CH= 0x00;
	CCAPM2=0x42;		//PCA模块2为PWM工作模式
	PCA_PWM2=0x80;	//PCA模块2输出6位PWM
	CCAP2L=0x20;//PWM占空比(40H-38H)/40H
	CCAP2H=0x20;//溢出时自动填装到CCAP0L里,实现无干扰更新
	CR=1;//启动PCA计数
	
	Timer0_Init();//定时器初始化
	
	while(1)
	{
		Key_Scan();
	}
}

void Timer0_Isr(void) interrupt 1
{
	//用于PCA模块的频率输入
	//0.83333x5=4.17微秒@12.000MHz
	//pwm频率为37.5Khz
}

void Timer1_Isr(void) interrupt 3
{
	static unsigned int T1Count1;
		T1Count1++;//每1ms进行一次++;
			
		if(T1Count1>=15)//20ms调用一次Key_Loop()函数
		{
			T1Count1=0;
			Key_Loop();
		}
		
}
  • Infr.c
#include <STC8G.H>

//注:该文件只是输出开关38khz的控制信号,还需另外一个信号源产生38khz信号
//本案例中使用stc8g1k08a的pca模块产生!
/**
  * @brief 红外时序延时函数//@12.000MHz
  * @param x10us 延时多少个10us
  * @retval 无
  */
void Delay_x10us(unsigned int x10us)		//@12.000MHz
{
	unsigned char data i;
	while(x10us)
	{
		i = 38;
		while (--i);
		x10us--;
	}
}
/**
  * @brief 红外发射信号
  * @param address 发送的地址
	* @param command 发送的命令/数据
  * @retval 无
  */
void Send_Byte(unsigned char address,unsigned char command)
{
	unsigned char i,j=0x01;
	P55=1;
	P55=0;
	Delay_x10us(845);
	P55=1;
	Delay_x10us(415);
	P55=0;
	for(i=0,j=0x01;i<8;i++)
	{
		if((address & j)==0)
		{
			Delay_x10us(52);
			P55=1;
			Delay_x10us(52);
			P55=0;
		}
		else
		{
			Delay_x10us(52);
			P55=1;
			Delay_x10us(155);
			P55=0;
		}
		j=j<<1;
	}
	for(i=0,j=0x01;i<8;i++)
	{
		if((address & j)==0)
		{
				Delay_x10us(52);
			P55=1;
			Delay_x10us(155);
			P55=0;
		}
		else
		{
			Delay_x10us(52);
			P55=1;
			Delay_x10us(52);
			P55=0;
		}
	j=j<<1;
	}
	for(i=0,j=0x01;i<8;i++)
	{
		if((command & j)==0)
		{
			Delay_x10us(52);
			P55=1;
			Delay_x10us(52);
			P55=0;
		}
		else
		{
			Delay_x10us(52);
			P55=1;
			Delay_x10us(155);
			P55=0;
		}
		j=j<<1;
	}
	for(i=0,j=0x01;i<8;i++)
	{
		if((command & j)==0)
		{
			Delay_x10us(52);
			P55=1;
			Delay_x10us(155);
			P55=0;
		}
		else
		{
			Delay_x10us(52);
			P55=1;
			Delay_x10us(52);
			P55=0;
		}
	j=j<<1;
	}
	P55=1;
}
  • Timer0.c
#include <STC8G.H>


/**
  * @brief  定时器初始化
  * @param 无
  * @retval 无
  */

void Timer0_Init(void)		//313微秒@12.000MHz
{
	AUXR |= 0x80;			//定时器时钟1T模式
	TMOD &= 0xF0;			//设置定时器模式
	AUXR |= 0x40;			//定时器时钟1T模式
	TMOD &= 0x0F;			//设置定时器模式
	
	TL0 = 0xFB;				//设置定时初始值
	TH0 = 0xFF;				//设置定时初始值

	TF0 = 0;				//清除TF0标志
	TR0 = 1;				//定时器0开始计时
	
	TL1 = 0x20;				//设置定时初始值
	TH1 = 0xD1;				//设置定时初始值
	TF1 = 0;				//清除TF1标志
	TR1 = 1;				//定时器1开始计时
	ET1 = 1;				//使能定时器1中断
	EA=1;
	PT1=0;
}
  • Key.c
#include <STC8G.H>

unsigned char Key_KeyNumber;

/**
  * @brief  外部调用主函数
  * @param 无
  * @retval Temp 传出在loop函数中得到的Key_KeyNumber值;
  */
unsigned char Key(void)
{
	unsigned char Temp=0;
	Temp=Key_KeyNumber;
	Key_KeyNumber=0;//对全局变量清0,防止下次中断进来
									//没按键按下仍传出上次按键值
	return Temp;
}

/**
  * @brief  定时器按周期进来一次则检测四个按键是否有按下的
  * @param 无
  * @retval keyNumber得到键值在loop中调用并返回值给NowState
  */
unsigned char Key_GetState()
{
unsigned char keyNumber=0;
	if(P30==0)keyNumber=1;
	if(P31==0)keyNumber=2;
	if(P32==0)keyNumber=3;
	if(P33==0)keyNumber=4;
return keyNumber;
}
/**
  * @brief  定时器周期扫描函数
  * @param 无
  * @retval 无
  */
void Key_Loop(void)
{
	static unsigned char NowState,LastState;//静态变量防止下次进来销毁
	LastState=NowState; 
	NowState=Key_GetState(); //调用按键按下函数,并把按下的值赋给NowState
	if(LastState==1 && NowState==0)//如果上次为1按下状态,这次为松开状态0则可以确定1键按下了
	{
	 Key_KeyNumber=1; //把得到的键值从中断中传出,放到全局变量Key_KeyNumber中
	}
	if(LastState==2 && NowState==0)
	{
	 Key_KeyNumber=2;
	}
	if(LastState==3 && NowState==0)//如果上次为1按下状态,这次为松开状态0则可以确定1键按下了
	{
	 Key_KeyNumber=3; //把得到的键值从中断中传出,放到全局变量Key_KeyNumber中
	}
	if(LastState==4 && NowState==0)//如果上次为1按下状态,这次为松开状态0则可以确定1键按下了
	{
	 Key_KeyNumber=4; //把得到的键值从中断中传出,放到全局变量Key_KeyNumber中
	}
}
  • Infr.h
#ifndef __INFR_H__
#define __INFR_H__

//注:该文件只是输出开关38khz的控制信号,还需另外一个信号源产生38khz信号
//本案例中使用stc8g1k08a的pca模块产生!
void Send_Byte(unsigned char address,unsigned char command);

#endif
  • Timer0.h
#ifndef __TIMER0_H__
#define __TIMER0_H__

void Timer0_Init(void);
	
#endif
  • Key.h
#ifndef __KEY_H__
#define __KEY_H__

unsigned char Key(void);
void Key_Loop(void);

#endif

小结

本案例通过软硬件的结合实现了红外遥控信号的发射功能。欢迎大家交流指正!

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SFR-小曾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值