您可以添加到网摘 让更多人关注此文章:
硬件:ATMega16(8MRC)+HT1621+一体化红外接收头
思路:红外解码采用中断捕捉方式(NEC编码),显示用液晶驱动HT1261
程序如下(WinAVR GCC环境编译):
#include <avr/io.h> #include <avr/delay.h> #include <avr/signal.h> #include <avr/interrupt.h> #include <avr/pgmspace.h>
#define HT1621_BIAS 0x29 // 设置LCD偏压发生器为1/3偏压,4个公共端 #define HT1621_RC256K 0x18 // 设置系统时钟源为片内RC(256KHz)振荡器 #define HT1621_SYSTEN 0x01 // 打开系统时钟振荡器 #define HT1621_SYSDIS 0x00 // 停止系统时钟振荡器和LCD偏压发生器 #define HT1621_LCDON 0x03 // 打开LCD偏压振荡器 #define HT1621_LCDOFF 0x02 // 关闭LCD偏压发生器 #define HT1621_RAMSIZE 0x10 // LCD显示RAM大小16个字节 #define HT1621_TOPT 0xE0
#define HT1621_CS_SET PORTC|=(1<<PC4) #define HT1621_CS_CLR PORTC&=~(1<<PC4) #define HT1621_WR_SET PORTC|=(1<<PC3) #define HT1621_WR_CLR PORTC&=~(1<<PC3) #define HT1621_DATA_SET PORTC|=(1<<PC2) #define HT1621_DATA_CLR PORTC&=~(1<<PC2) #define IR_RX (PIND&(1<<PD2))
unsigned char lcd_dis_buf[16] ={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; unsigned char capt_vect_cnt=0; unsigned char ir_rx_data_flag=0; unsigned char ir_rx_complete_flag=0; unsigned char bitcnt=0; unsigned int ir_plus[33]; unsigned int user_code=0; unsigned int operate_code=0; const unsigned char lcd7_code[] PROGMEM= { 0xF5, // 0 0x05, // 1 0xB6, // 2 0x97, // 3 0x47, // 4 0xD3, // 5 0xF3, // 6 0x85, // 7 0xF7, // 8 0xD7, // 9 0xE7, // A 0x73, // B 0xF0, // C 0x37, // D 0xF2, // E 0xE2, // F 0x70, // L 0x67, // H 0xE0, // R 0x23 // n }; //************************************************************** //*名称: void ht1621_send_bit_h(unsigned char nbit,n) * //*功能: 向ht1621发送n位bit,先发送高位 * //*参数: nbit 送的bit位 len 发送bit的位数 * //*返回: 无 * //************************************************************** void ht1621_send_bit_h(unsigned char nbit,unsigned char len) { unsigned char temp; for(temp=0;temp<len;temp++) { HT1621_WR_CLR; if((nbit&0x80)==0x80) { HT1621_DATA_SET; } else { HT1621_DATA_CLR; } HT1621_WR_SET; nbit<<=1; } } //************************************************************** //*名称: void ht1621_send_bit_h(unsigned char nbit,n) * //*功能: 向ht1621发送n位bit,先发送低位 * //*参数: nbit 送的bit位 len 发送bit的位数 * //*返回: 无 * //************************************************************** void ht1621_send_bit_l(unsigned char nbit,unsigned char len) { unsigned char temp; for(temp=0;temp<len;temp++) { HT1621_WR_CLR; if((nbit&0x01)==0x01) { HT1621_DATA_SET; } else { HT1621_DATA_CLR; } HT1621_WR_SET; nbit>>=1; } } //************************************************************** //*名称: void ht1621_send_cmd(unsigned char cmd) * //*功能: 向ht1621发送命令 * //*参数: cmd 发送的命令 * //*返回: 无 * //************************************************************** void ht1621_send_cmd(unsigned char cmd) { HT1621_CS_CLR; ht1621_send_bit_h(0x80,3); // 发送命令模式100 ht1621_send_bit_h(cmd,9); // 发送命令 HT1621_CS_SET; }
//************************************************************** //*名称: void ht1621_write_byte(unsigned char byte,address) * //*功能: 向ht1621写显示数据 * //*参数: byte 数据字节 address 数据地址 * //*返回: 无 * //************************************************************** void ht1621_write_byte(unsigned char byte,unsigned char address) { address<<=2; HT1621_CS_CLR; HT1621_WR_CLR; ht1621_send_bit_h(0xA0,3); // 发送写数据模式101 ht1621_send_bit_h(address<<2,6); // 发送地址 ht1621_send_bit_l(byte,4); // 发送数据字节 HT1621_CS_SET;HT1621_WR_SET; }
//***************************************************************** //*名称:void ht1621_write_string(unsigned char *prt,address,len) * //*功能:向ht1621写入一组显示数据 * //*参数:prt 指向字节数组的指针 * //* address 数据首地址 * //* len 数组的长度 * //*返回:无 * //***************************************************************** void ht1621_write_string(unsigned char *prt,unsigned char address,unsigned char len) { unsigned char temp; HT1621_CS_CLR; ht1621_send_bit_h(0xA0,3); //发送写数据模式101 ht1621_send_bit_h(address<<2,6); //发送地址 if((len+address)>HT1621_RAMSIZE) { len=HT1621_RAMSIZE-address; } for(temp=0;temp<len;temp++) { ht1621_send_bit_l(*prt++,8); //发送数据字节 } HT1621_CS_SET; } //*********************************************************** //*名称:void ht1621_int() * //*功能:ht1621初始化 * //*参数:无 * //*返回:无 * //*********************************************************** void ht1621_int(void) { ht1621_send_cmd(HT1621_BIAS); // 设置LCD偏压发生器为1/3偏压,4个公共端 ht1621_send_cmd(HT1621_SYSTEN); // 打开系统时钟振荡器 ht1621_send_cmd(HT1621_LCDON); // 打开LCD偏压振荡器 ht1621_send_cmd(HT1621_RC256K); // 启动内部256KRC 振荡器 } //*********************************************************************************** //*名称: delay_nus(unsigned int nms) * //*功能: 延时nms * //*参数: 无 * //*返回: 无 * //*********************************************************************************** void delay_nus(unsigned int nms) { while(nms--) { _delay_loop_2(2); } }
SIGNAL(TIMER1_CAPT_vect) { unsigned int temp; temp=ICR1; // 获取间隙+脉冲的时间 TCNT1=0x0000; if(temp>1024&&temp<1225) // 判断数据0信号 { temp=0; } else if(temp>2145&&temp<2345) // 判断数据1信号 { temp=0x8000; } else if(temp>13400&&temp<14600) // 判断引导码信号 { bitcnt=0; user_code=0; operate_code=0; return; // 返回,等待下次开始接收 } else // 干扰信号 { return; } bitcnt++; if(bitcnt<17) //开始接收前16位 { user_code>>=1; user_code|=(unsigned int)temp; } /*else if(bitcnt==16) { user_code=user_code|(unsigned int)temp; }*/ else if(bitcnt<33) //开始接收后16位 {operate_code>>=1; operate_code|=(unsigned int)temp; } if(bitcnt==32) //接收完最后一位 { ir_rx_complete_flag=1; } }
SIGNAL(SIG_INTERRUPT0) { unsigned char i; unsigned char plus_width=0; while(!IR_RX) // 计算引导电平的宽度 { _delay_loop_2(200); plus_width++; } if(plus_width<80) // 如果低电平不到8ms即视为是干扰信号 { return; } plus_width=0;
while(IR_RX) // 计算4.5ms低电平宽度 { _delay_loop_2(200); plus_width++; } if(plus_width<30) // 如果不到3ms即视为2.5ms连发信号 { return; } if(plus_width<40) // 如果不到4ms视为错误信号,放弃接收 { return; } for(i=0;i<16;i++) { while(!IR_RX); // 等待0.56ms低电平结束 plus_width=0; while(IR_RX) // 计算高电平宽度 { _delay_loop_2(200); plus_width++; } user_code>>=1; if(plus_width>8) { user_code|=0x8000; } } for(i=0;i<16;i++) { while(!IR_RX); // 等待0.56ms低电平结束 plus_width=0; while(IR_RX) // 计算高电平宽度 { _delay_loop_2(200); plus_width++; } operate_code>>=1; if(plus_width>8) { operate_code|=0x8000; } } ir_rx_complete_flag=1; }
int main(void) {
TCCR1A= 0x00; // 定时器工作在普通模式 TCCR1B=(1<<ICNC1)|(1<<CS11); // PD6/ICP端口捕捉噪声抑制,下降沿触发捕捉中断中断,定时器8分频 TIMSK=(1<<TICIE1); // 外部捕获中断使能 PORTC|=0X1E; // PC2-P4输出高电平 DDRC|=0X1E; // PC2-PC4设置为输出口 ht1621_int(); sei(); lcd_dis_buf[10]=pgm_read_byte(lcd7_code+(char)(user_code/256/16)); lcd_dis_buf[9]=pgm_read_byte(lcd7_code+(char)(user_code/256%16)); lcd_dis_buf[8]=pgm_read_byte(lcd7_code+(char)(user_code%256/16)); lcd_dis_buf[7]=pgm_read_byte(lcd7_code+(char)(user_code%256%16)); lcd_dis_buf[4]=pgm_read_byte(lcd7_code+(char)(operate_code/256/16)); lcd_dis_buf[3]=pgm_read_byte(lcd7_code+(char)(operate_code/256%16)); lcd_dis_buf[2]=pgm_read_byte(lcd7_code+(char)(operate_code%256/16)); lcd_dis_buf[1]=pgm_read_byte(lcd7_code+(char)(operate_code%256%16)); while(1) { if(ir_rx_complete_flag==1) { lcd_dis_buf[10]=pgm_read_byte(lcd7_code+(char)(user_code/256/16)); lcd_dis_buf[9]=pgm_read_byte(lcd7_code+(char)(user_code/256%16)); lcd_dis_buf[8]=pgm_read_byte(lcd7_code+(char)(user_code%256/16)); lcd_dis_buf[7]=pgm_read_byte(lcd7_code+(char)(user_code%256%16)); lcd_dis_buf[4]=pgm_read_byte(lcd7_code+(char)(operate_code/256/16)); lcd_dis_buf[3]=pgm_read_byte(lcd7_code+(char)(operate_code/256%16)); lcd_dis_buf[2]=pgm_read_byte(lcd7_code+(char)(operate_code%256/16)); lcd_dis_buf[1]=pgm_read_byte(lcd7_code+(char)(operate_code%256%16)); ir_rx_complete_flag=0; } ht1621_write_string(lcd_dis_buf,0x00,16); } }
|