|
楼主 |
发表于 2005-2-21 10:47:07
|
显示全部楼层
这是我的源程序
/*****************************************
红外线遥控器解码程序
输入数据:无
输出:
作者:蒋剑东 广西南宁
CPU: M16L 晶振:片外8M
修改时间:2004-11-22
*****************************************/
#include "iom16.h"
#include "stdio.h"
#include "macros.h" // 常用的宏定义
#define uchar unsigned char
#define uint unsigned int
#define led_on PORTB |= 1<<3;
#define led_off PORTB &= ~(1<<3);
#define buz_off PORTD |= (1<<7);
#define buz_on PORTD &= ~(1<<7);
#define led1_on PORTA &= ~(1<<5);
#define led1_off PORTA |= (1<<5);
#define led2_on PORTA &= ~(1<<6);
#define led2_off PORTA |= (1<<6);
#define led3_on PORTA &= ~(1<<7);
#define led3_off PORTA |= (1<<7);
//----------------- 延时程序START ---------------------------
void delay_nms(uint count)
{
uint i,j;
for( j=0;j<count;j++ )
{
for( i=0;i<999;i++ )
{
asm("wdr");
}
}
}
void delay_nus(uint count)
{
uint i;
for( i=0;i<count;i++ )
{
asm("wdr");
}
}
//----------------- 延时程序END ---------------------------
void cpu_init(void)
{
DDRA = DDRB = DDRC = DDRD = 0XFF; // 不用的I/O口全部配置为输出
DDRD &= ~(1<<2); // PD2为INT0,配置为输入
PORTD &= ~(1<<2); // PD2上拉电阻禁止
UBRR = 0x33; // 波特率9600
UCR = 0x18;
MCUCR |= (1<<1);
MCUCR &= ~(1<<0); // 等效于MCUCR = 0x02; 设定INT0为下降沿触发中断
GICR |= (1<<6); // 开INT0中断
TIMSK = 0x00; // timer interrupt sources
WDTCR = 0B00001001; // 使能看门狗,溢出周期32.5ms
led1_off led2_off led3_off buz_off
SEI(); // 打开全局中断
}
void main(void)
{
cpu_init();
puts("hellow\r");
while(1)
{
asm("wdr");
}
}
//----------------- INT0中断服务程序 START ---------------------------
#pragma interrupt_handler int0_isr:2
void int0_isr(void)
{
uchar bit=0;
uchar i,cycle,continue_count;
uint data,temp;
uint user_code,user_code_not;
CLI(); // 关闭全局中断
for( i=0;i<8;i++ )
{
delay_nms(1);
if( (PIND&0B00000100)==0B00000100 )
{
goto ret; //目的是检测在8毫秒内如果出现高电平就退出解码程序
}
}
//while( (PIND&0B00000100)==0B00000000 );
temp = 8000;
while( ((PIND&0B00000100)==0B00000000) && (temp!=0) ){temp--;} // 等待4.5ms高电平的到来,避开9毫秒低电平引导脉冲
// temp--需0.25us, temp=8000可实现2ms延时,防止干扰脉冲造成的死机。
delay_nus(5412); // 延时4.74毫秒避开4.5毫秒的结果码
for( i=0;i<13;i++ ) // 接收用户码,存入user_code中
{
//while( (PIND&0B00000100)==0B00000000 ); // 等待地址码第一位的高电平信号
temp = 4000;
while( ((PIND&0B00000100)==0B00000000) && (temp!=0) ){temp--;} // 等待地址码第一位的高电平信号
// temp--需0.25us, temp=4000可实现1ms延时,防止干扰脉冲造成的死等待。
delay_nus(1002); // 高电平开始后用882微秒的时间尺去判断信号此时的高低电平状态
if( (PIND&0B00000100)==0B00000100 ) // 检测到高电平1的话说明该位为1,延时1毫秒等待脉冲高电平结束
{
user_code |= (1<<i);
delay_nus(1137);
}
else // 检测到低电平0的话,说明该位为0,继续检测下一位
{
user_code &= ~(1<<i);
} // 检测到低电平0的话,说明该位为0,继续检测下一位
}
for( i=0;i<13;i++ ) // 接收用户码取反,存入user_code_not中
{
temp = 4000;
while( ((PIND&0B00000100)==0B00000000) && (temp!=0) ){temp--;} // 等待地址码第一位的高电平信号
// temp--需0.25us, temp=4000可实现1ms延时,防止干扰脉冲造成的死等待。
delay_nus(1002); // 高电平开始后用882微秒的时间尺去判断信号此时的高低电平状态
if( (PIND&0B00000100)==0B00000100 ) // 检测到高电平1的话说明该位为1,延时1毫秒等待脉冲高电平结束
{
user_code_not |= (1<<i);
delay_nus(1137);
}
else // 检测到低电平0的话,说明该位为0,继续检测下一位
{
user_code_not &= ~(1<<i);
} // 检测到低电平0的话,说明该位为0,继续检测下一位
}
for( i=0;i<16;i++ ) // 开始接收16位数据,存入字变量data中,dataH= ~data dataL= data
{
temp = 4000;
while( ((PIND&0B00000100)==0B00000000) && (temp!=0) ){temp--;} // 等待数据码第一位的高电平信号
// temp--需0.25us, temp=4000可实现1ms延时,防止干扰脉冲造成的死等待。
delay_nus(1002); // 高电平开始后用882微秒的时间尺去判断信号此时的高低电平状态
if( (PIND&0B00000100)==0B00000100 ) // 检测到高电平1的话说明该位为1,延时1毫秒等待脉冲高电平结束
{
data |= (1<<i); // dataH= ~data dataL= data
delay_nus(1137);
}
else // 检测到低电平0的话,说明该位为0,继续检测下一位
{
data &= ~(1<<i);
}
}
user_code_not ^=0xffff; // 取反
user_code_not &=0x1fff;
user_code &=0x1fff;
temp = (data>>8);
temp ^=0xffff; // 取反
temp &=0x00ff;
data &=0x00ff;
if( (temp==data)&&(user_code_not==user_code) ) // 校验
{
if ( data==0x0001) PORTA ^= (1<<5);
else if ( data==0x0002) PORTA ^= (1<<6);
else if ( data==0x0003) PORTA ^= (1<<7);
UDR = data; // data
while(!(USR&0X40));
USR|=0x40;
bit = 1;
//buz_on 放在这里不好控制蜂鸣器响的长度,因为若改变delay_nus(500);中的参数会导致下面“连续按键检测”
//delay_nus(500); 工作不正常,所以将这一段移至“连续按键检测”之后。
//buz_off
}
// 检测是否有连续按键 START
cycle = 7; // 总共延时7毫秒
continue_count = 0;
delay_nms(20); // 延时20毫秒,然后等待连续按键产生的9毫秒开始信号
while( cycle!=0 ) // 如果7毫秒之内没有检测到低电平则说明没有连续按键,退出
{
if( (PIND&0B00000100)==0B00000000 )
{
continue_count++;
if( continue_count>8 ) // 连续检测到8次以上才发送数据,防止短按时发送多次数据
{
UDR = data; // data
while(!(USR&0X40));
USR|=0x40;
PORTD ^= (1<<7);
}
cycle = 7; // 有连续按键,重置延时周期数
delay_nms(104); // 延时104毫秒,然后等待下一个9毫秒开始信号
buz_off
}
delay_nms(1); // 每隔一毫秒检测一次
cycle--;
}
// 检测是否有连续按键 END
if( bit==1 )
{
buz_on
delay_nus(1000);
buz_off
}
ret:
SEI(); // 打开全局中断
}
//----------------- INT0中断服务程序 END ---------------------------
-----此内容被Jacky于2005-02-21,10:48:18编辑过 |
|