本人現(xiàn)在在使用MSP430做系統(tǒng),現(xiàn)在做了一個(gè)按鍵紅外發(fā)送數(shù)組程序,和一個(gè)接收紅外信息之后,正確識(shí)別數(shù)組,并將數(shù)組發(fā)送到串口助手以比較發(fā)送和接收的數(shù)據(jù)是否有誤差。這已經(jīng)通過硬件下載調(diào)試了,沒有誤碼,可以直接使用。本人使用的紅外芯片是美國安捷倫公司的HSDL-3201,最大支持115.2Kb/S的紅外發(fā)送。由于程序只是在功能上實(shí)現(xiàn)了,還沒有進(jìn)一步優(yōu)化。 1、按鍵之后紅外發(fā)送一個(gè)數(shù)組
#include<msp430x417.h> #include"led.c" #include"lcd_modle.c" //將其他的函數(shù)模塊包涵在一個(gè)文件中 #define uchar unsigned char #define uint unsigned int #define TIME 6000 //延時(shí)時(shí)間常數(shù),延時(shí)時(shí)間為183ms,其實(shí)延時(shí)時(shí)間常數(shù)完全可以設(shè)置得小一些,但是由于按鍵抖動(dòng)得厲害,所以設(shè)這么大
//在IAR EW430 編譯器軟件中如何實(shí)現(xiàn)高精度軟件延時(shí),利用IAR EW430 內(nèi)部延時(shí)子程序即可方便地實(shí)現(xiàn) #define CPU_F ((double)1048576) //這里是你當(dāng)前MSP430 CPU的主頻頻率,即CPU的MCLK,單位為HZ #define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0)) #define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0)) //************************************************************************
//要發(fā)送的數(shù)據(jù),用關(guān)鍵字"const" 聲明,不放在RAM區(qū) const uchar a[6]={0x66,0x83,0x08,0x00,0xE8,0x84}; //加號(hào) const uchar b[6]={0x66,0x83,0x20,0x00,0xF6,0x84}; // 減號(hào) const uchar c[6]={0x66,0x83,0x10,0x00,0xE2,0x84}; //左箭頭 const uchar d[6]={0x66,0x83,0x18,0x00,0xE5,0x44}; //右箭頭 const uchar e[6]={0x66,0x83,0x28,0x00,0xF1,0x44}; //OK const uchar f[6]={0x66,0x83,0x30,0x00,0xFB,0x44}; //C/II const uchar g[6]={0x66,0x83,0x38,0x00,0xFC,0x84}; //開閥 const uchar h[6]={0x66,0x83,0x40,0x00,0xDE,0x84}; //關(guān)閥 const uchar i[6]={0x66,0x83,0x48,0x00,0xD9,0x44}; //左右箭頭同時(shí)按下
extern void lcd_modle(); //利用函數(shù)原型(函數(shù)聲明)擴(kuò)展函數(shù)的作用域, void led(); //利用函數(shù)原型(函數(shù)聲明)擴(kuò)展函數(shù)的作用域, extern可以省略
uchar keybuf=0x00; //鍵值,全局變量的初始化 uchar keytime=0x06; //判斷連鍵時(shí),定時(shí)中斷的次數(shù),初始化為6,即連鍵時(shí)間間隔設(shè)置 //************************************************************************ void settime(long uint ti) //設(shè)置定時(shí)時(shí)間 { CCR0=ti; //定時(shí)時(shí)間 }
void gostopA(uchar a) //打開或是關(guān)閉定時(shí)器,其中a為判斷標(biāo)志 { if(a==1) { TACTL=TASSEL0+TACLR+MC0; //清TAR(消除定時(shí)器的方向記憶特性),設(shè)置定時(shí)器工作在增計(jì)數(shù)模式,記得選擇ASCLK作為定時(shí)時(shí)鐘 settime(TIME); } else if(a==0) { TACTL&=~MC0; //定時(shí)器暫停計(jì)數(shù),TACTL=MC_0;但是并不發(fā)生復(fù)位,當(dāng)定時(shí)器重新計(jì)數(shù)時(shí),計(jì)數(shù)器從暫停時(shí)的值開始 } }
//************************************************************************ void timerainit() //定時(shí)器A的初始化 { TACTL=TASSEL0+TACLR; //選ASCLK,清TAR, 剛開始并沒有計(jì)數(shù) CCTL0=CCIE; //先開允許比較中斷 settime(TIME); //設(shè)置時(shí)間放在允許中斷的后面 }
//************************************************************************ void gostopkey(uchar sw) //打開或者關(guān)閉按鍵中斷 { if(sw==0) P1IE&=0X00; //關(guān)閉按鍵中斷 else if (sw==1) P1IE|=0XFF; //打開按鍵中斷允許 }
//************************************************************************ uchar conkey() //連續(xù)按鍵的判斷和處理,此模塊放在定時(shí)中斷程序中,不知是否需要清定時(shí)中斷標(biāo)志(CCIFG0=0;),不需要消除,它會(huì)自動(dòng)消除,跳出定時(shí)中斷 { uchar x=0x00; if((P1IN&0XFF)==0X00) //單獨(dú)按鍵,或者是連續(xù)按鍵松開之后 { //沒有鍵按下 gostopA(0); //關(guān)閉定時(shí)器 gostopkey(1); //打開按鍵中斷 } else //連續(xù)按鍵的情況 { if(keytime==0) //連續(xù)按鍵的時(shí)間到 { keytime=0x06; //重新置值 if((P1IN&0XFF)==0X80) { x=1; //給全局變量鍵值賦值 } else if((P1IN&0XFF)==0X40) { x=2; } else if((P1IN&0XFF)==0X20) { x=3; } else if((P1IN&0XFF)==0X10) { x=6; } else if((P1IN&0XFF)==0X08) { x=4; } else if((P1IN&0XFF)==0X04) { x=7; } else if((P1IN&0XFF)==0X02) { x=5; } else if((P1IN&0XFF)==0X01) { x=8; } else if((P1IN&0XFF)==0X18) //組合鍵,4、6組合鍵,組合鍵有效的時(shí)間為:按鍵之后:183ms*6,即時(shí)間間隔為連鍵時(shí)間間隔 { x=9; } else //其他情況 { x=0x00; gostopA(0); //關(guān)閉定時(shí)器 gostopkey(1); //打開按鍵中斷 }
} else //連續(xù)按鍵的時(shí)間沒有到 keytime--; } return(x); }
//************************************************************************ #pragma vector=TIMERA0_VECTOR //CCRO中斷,為單源中斷,自動(dòng)消除中斷標(biāo)志 __interrupt void Timer_A0(void) //定時(shí)器中斷 { keybuf=conkey(); //獲取連續(xù)按鍵值,0x00代表沒有連續(xù)按鍵 }
//************************************************************************ void keyinit() //按鍵初始化 { P1DIR&=0X00; //P1口接8個(gè)按鍵,全部設(shè)為輸入 P1IES&=0X00; //設(shè)為上升沿中斷 P1IE|=0XFF; //全部允許中斷 P1IFG&=0X00; //清中斷標(biāo) }
//************************************************************************ uchar keycode() //判斷單個(gè)的鍵值 { uchar y, q0=0; if((P1IN&0XFF)==0X80)//不使用中斷標(biāo)志查詢中斷源,在按鍵中斷中不識(shí)別組合鍵 { y=1; q0=1; } else if((P1IN&0XFF)==0X40) { y=2; q0=1; } else if((P1IN&0XFF)==0X20) { y=3; q0=1; } else if((P1IN&0XFF)==0X10) { y=6; q0=1; } else if((P1IN&0XFF)==0X08) { y=4; q0=1; } else if((P1IN&0XFF)==0X04) { y=7; q0=1; } else if((P1IN&0XFF)==0X02) { y=5; q0=1; } else if((P1IN&0XFF)==0X01) { y=8; q0=1; } else y=0x00; //沒有按鍵按下,或者是其他情況 if(q0==1) //有按鍵按下的情況,為判斷是否按鍵連續(xù)做準(zhǔn)備 { gostopA(1); //開啟定時(shí)中斷 gostopkey(0); //關(guān)閉按鍵中斷 } return(y); }
//************************************************************************ #pragma vector=PORT1_VECTOR __interrupt void port1_vector(void) { keybuf=keycode(); P1IFG=0X00;//消除中斷標(biāo)志,跳出按鍵中斷 }
//************************************************************************ void zijiesend(uchar m) //以19200bit/S紅外發(fā)送一個(gè)字節(jié), { uchar n; P5OUT&=0xdf;P5OUT|=0X20;delay(4);_NOP();_NOP();_NOP();//發(fā)送起始位,設(shè)置波特率 for(n=1;n<=8;n++) //8個(gè)數(shù)據(jù)位,發(fā)8次 { if((m&0x01)==0){P5OUT&=0Xdf;P5OUT|=0X20;delay(4);_NOP();} //先發(fā)最低位(即最右邊那位) else {P5OUT|=0X20;delay(6);} m=m>>0x01; //將要發(fā)送的數(shù)據(jù)右移一位 } P5OUT|=0x20; //發(fā)送停止位 delay(7);_NOP();_NOP();_NOP();_NOP();//延時(shí)1個(gè)停止位 }
//************************************************************************ void shuzusend(const uchar *c) //使用指針調(diào)用數(shù)組 { uchar i,*p; //i為數(shù)組元素個(gè)數(shù) p=(uchar *)c; //指針類型轉(zhuǎn)換 keybuf=0x00; //清零 for(i=1;i<=6;i++) //數(shù)組有6個(gè)元素,發(fā)送6次 { zijiesend(*p); //發(fā)送數(shù)組元素 p++; //移到下一個(gè)元素 delay_us(500); //發(fā)送完一個(gè)字節(jié)等待500微秒 } delay_ms(10); //發(fā)送完一個(gè)數(shù)組等待10毫秒 }
//************************************************************************ main() //連續(xù)去抖動(dòng),按鍵機(jī)械扛抖動(dòng)能力很差,加入了組合鍵(注意組合鍵識(shí)別的有效時(shí)鍵) { WDTCTL=WDTPW+WDTHOLD;//關(guān)看門狗 P2DIR|=0X04; P2OUT|=0X04; //在P2.2口輸出高電位,開啟紅外部分電源 keyinit(); //按鍵初始化 timerainit(); //定時(shí)器初始化 P5DIR|=0X20; //設(shè)置P5.5為輸出端 delay_ms(150); //進(jìn)入循環(huán)前延時(shí),等待低速時(shí)鐘穩(wěn)定 _EINT(); //開總中斷 while(1) { switch(keybuf) //使用keybuf作為判斷標(biāo)志 { case 0x00 : break; case 1 : shuzusend(a); break; case 2 : shuzusend(b); break; case 3 : shuzusend(c); break; case 4 : shuzusend(d); break; case 5 : shuzusend(e); break; case 6 : shuzusend(f); break; case 7 : shuzusend(g); break; case 8 : shuzusend(h); break; case 9 : shuzusend(i); break; //4、6組合鍵 default : break; } } }
//定時(shí)器延時(shí)時(shí)間常數(shù)本來可以設(shè)得比較小的,但設(shè)置得小的時(shí)候,由于抖動(dòng)厲害,會(huì)發(fā)兩次數(shù)據(jù);若是需要修改連鍵識(shí)別時(shí)間間隔,直接更改"keytime"的值就可以了 //低速時(shí)鐘需要上百毫秒的建立時(shí)間才能穩(wěn)定下來。
2、紅外接收數(shù)組,并將接收到的數(shù)組以19200b/S的速率,經(jīng)485發(fā)送PC串口,并在串口調(diào)試助手上顯示出來:
#include<msp430x417.h> #include"delay.c" #define uchar unsigned char #define uint unsigned int
//在IAR EW430 編譯器軟件中如何實(shí)現(xiàn)高精度軟件延時(shí),利用IAR EW430 內(nèi)部延時(shí)子程序即
可方便地實(shí)現(xiàn) #define CPU_F ((double)1048576) //這里是你當(dāng)前MSP430 CPU的主頻
頻率,即CPU的MCLK,單位為HZ #define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0)) #define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0)) //************************************************************************
uchar a[6]={0}; //定義數(shù)組a來存放紅外接收到的數(shù)據(jù),并初始化為0,
uchar zijiereceive()//用關(guān)系統(tǒng)總中斷,查詢中斷標(biāo)志的方案實(shí)現(xiàn) { uchar s,t=0x00; for(;;) //沒有字節(jié)發(fā)送則一直等待 if((P2IFG&0X01)==0X01) { P2IFG&=0XFE; //先將中斷標(biāo)志清零 break; }
delay(10); //從檢測到起始位(下降沿)到第一個(gè)采樣點(diǎn)的延時(shí) if((P2IFG&0X01)==0X01){s=0x00;P2IFG&=0XFE;} else {s=0x01;P2IFG&=0XFE;} t+=s; delay(7); if((P2IFG&0X01)==0X01){s=0x00;P2IFG&=0XFE;} else {s=0x01;P2IFG&=0XFE;} s<<=1; t+=s; delay(7); if((P2IFG&0X01)==0X01){s=0x00;P2IFG&=0XFE;} else{s=0x01;P2IFG&=0XFE;} s<<=2; t+=s; delay(4); if((P2IFG&0X01)==0X01){s=0x00;P2IFG&=0XFE;} else {s=0x01;P2IFG&=0XFE;} s<<=3; t+=s; delay(4); if((P2IFG&0X01)==0X01){s=0x00;P2IFG&=0XFE;} else {s=0x01;P2IFG&=0XFE;} s<<=4; t+=s; delay(3); if((P2IFG&0X01)==0X01){s=0x00;P2IFG&=0XFE;} else {s=0x01;P2IFG&=0XFE;} s<<=5; t+=s; delay(3); if((P2IFG&0X01)==0X01){s=0x00;P2IFG&=0XFE;} else {s=0x01;P2IFG&=0XFE;} s<<=6; t+=s; delay(6); if((P2IFG&0X01)==0X01){s=0x00;P2IFG&=0XFE;} else {s=0x01;P2IFG&=0XFE;} s<<=7; t+=s; return(t); }
//************************************************************************ void shuzureceive( uchar *a) //使用指針完成一個(gè)數(shù)組的接收,并將他們按順序存入
已定義的數(shù)組。 { uchar i,*p; //定義循環(huán)常數(shù)和指針變量 p=a; //將數(shù)組首地址賦給指針p P2IES|=0X01; //P2.0設(shè)為下降沿中斷觸發(fā) P2IFG&=0XFE; //將中斷標(biāo)志清零,初始化 for(i=1;i<=6;i++) { *p=zijiereceive(); //存入一個(gè)字節(jié) p++; //更新存儲(chǔ)單元 } }
//************************************************************************ void transmit(uchar m) //485以19200bit/S發(fā)送一個(gè)字節(jié), { uchar n; P5OUT&=0xdf; //發(fā)送起始位 delay(6); //設(shè)置波特率 for(n=1;n<=8;n++) //8個(gè)數(shù)據(jù)位,發(fā)8次 { if((m&0x01)==0)P5OUT&=0Xdf;//先發(fā)最低位(即最右邊那位) else P5OUT|=0X20; delay(6); m=m>>0x01; //將要發(fā)送的數(shù)據(jù)右移一位 } P5OUT|=0x20; //發(fā)送停止位 delay(8);_NOP(); //延時(shí)1個(gè)停止位 }
//************************************************************************ void send( uchar *c) //使用指針調(diào)用數(shù)組,485發(fā)送一個(gè)數(shù)組 { uchar i,*p; //i為數(shù)組元素個(gè)數(shù) p=c; //指針類型轉(zhuǎn)換 for(i=1;i<=6;i++) //數(shù)組有6個(gè)元素,發(fā)送6次 { transmit(*p); //發(fā)送數(shù)組元素 p++; //移到下一個(gè)元素 } }
//************************************************************************ main() { WDTCTL=WDTPW+WDTHOLD;//關(guān)看門狗 _DINT();//關(guān)總中斷
P2DIR|=0X04; P2OUT|=0X04; //輸出高電平,開啟紅外部分電源,這也是用的P2口 P5DIR|=0X20; //設(shè)置P5.5為輸出端 delay_ms(20); // 等待低速時(shí)鐘穩(wěn)定
while(1) { shuzureceive(a); //紅外接收一個(gè)數(shù)組 send(a); //485發(fā)送接到的數(shù)據(jù) }
} //不允許中斷,但中斷標(biāo)志仍然存在,須用軟件清零
實(shí)驗(yàn)結(jié)果(串口助手上顯示的數(shù)據(jù)): 00 66 83 38 00 FC 84 00 66 83 18 00 E5 44 66 83 18 00 E5 44 66 83 18 00 E5 44 66 83 18 00 E5 44 00 66 83 18 00 E5 44 66 83 18 00 E5 44 66 83 18 00 E5 44 00 66 83 38 00 FC 84 66 83 38 00 FC 84 00 66 83 30 00 FB 44 66 83 30 00 FB 44 00 00 00 00 00 66 83 08 00 E8 84 66 83 08 00 E8 84 66 83 08 00 E8 84 66 83 08 00 E8 84 00 66 83 20 00 F6 84 66 83 20 00 F6 84 66 83 20 00 F6 84 66 83 20 00 F6 84
|