//PPM 解码程序 //用INT0接PPM信号 //T0计数,用来测量脉宽 //注意,这个不是标准的PPM信号,刚好和PPM信号相位相反 //测得的PPM信号在LCD上显示 //PPM信号取自天地飞6A接收机 //时间:2012年2月15日0:22:31 # include # include # define DataPort P0 sbit RS=P2^4; sbit RW=P2^5; sbit EN=P2^6; unsigned char channel=0,i=0; unsigned int xdata PPM_channel1[10],PPM_channel2[10],PPM_channel3[10],PPM_channel4[10],PPM_channel5[10],PPM_channel6[10]; bit Timer0_OverFlowFlag=0;//定时器0的溢出标志,如果溢出,则有问题; unsigned char qian,bai,shi,ge; # define RS_CLR RS=0; # define RS_SET RS=1; # define RW_SET RW=1; # define RW_CLR RW=0; # define EN_CLR EN=0; # define EN_SET EN=1; //和LCD显示有关的函数定义 void LCD_Check_Busy(void); //查忙函数 void LCD_Clear(void);//清屏函数 void LCD_Init(void);//lcd初始化函数 void LCD_Write_Com(unsigned char com);//控制字写入函数 void LCD_Write_Data(unsigned char Data);//数据写入函数 void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data);//写入单个字符 void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s);//写入字符串 unsigned int filter(unsigned int *s);//中值平局滤波; void DepartNum(unsigned int temp);//用于分解要显示的数据 void DelayUs2x(unsigned char t); void DelayMs(unsigned int t); void main(void) { unsigned char *InitIform; unsigned int temp; InitIform="Init_is_OK"; LCD_Init(); DelayMs(10); LCD_Write_String(3,0,InitIform); //初始化Timer0 TMOD=0x01;//timer0 方式1 ET0=1;//允许timer0中断 //初始化INT0 IT0=1;//负跳变触发中断; EX0=1; EA=1; DelayMs(10000); while(1) { temp=filter(PPM_channel1); DepartNum(temp); LCD_Write_Char(0,0,'A'); LCD_Write_Char(1,0,qian); LCD_Write_Char(2,0,bai); LCD_Write_Char(3,0,shi); LCD_Write_Char(4,0,ge); temp=filter(PPM_channel2); DepartNum(temp); LCD_Write_Char(5,0,'B'); LCD_Write_Char(6,0,qian); LCD_Write_Char(7,0,bai); LCD_Write_Char(8,0,shi); LCD_Write_Char(9,0,ge); temp=filter(PPM_channel3); DepartNum(temp); LCD_Write_Char(10,0,'C'); LCD_Write_Char(11,0,qian); LCD_Write_Char(12,0,bai); LCD_Write_Char(13,0,shi); LCD_Write_Char(14,0,ge); temp=filter(PPM_channel4); DepartNum(temp); LCD_Write_Char(0,1,'D'); LCD_Write_Char(1,1,qian); LCD_Write_Char(2,1,bai); LCD_Write_Char(3,1,shi); LCD_Write_Char(4,1,ge); temp=filter(PPM_channel5); DepartNum(temp); LCD_Write_Char(5,1,'E'); LCD_Write_Char(6,1,qian); LCD_Write_Char(7,1,bai); LCD_Write_Char(8,1,shi); LCD_Write_Char(9,1,ge); temp=filter(PPM_channel6); DepartNum(temp); LCD_Write_Char(10,1,'F'); LCD_Write_Char(11,1,qian); LCD_Write_Char(12,1,bai); LCD_Write_Char(13,1,shi); LCD_Write_Char(14,1,ge); // DelayMs(1000); } } void DelayUs2x(unsigned char t) { while(--t); } void DelayMs(unsigned int t) { while(t--) { //大致延时1mS DelayUs2x(245); DelayUs2x(245); } } //查忙函数 void LCD_Check_Busy(void) { unsigned char i=255; DataPort= 0xff; RS_CLR; RW_SET; EN_SET; while(i--&&(DataPort&0x80)); EN_CLR; } //控制字写入函数,入口参数是控制字 void LCD_Write_Com(unsigned char com) { LCD_Check_Busy(); RS_CLR; RW_CLR; DataPort=com; EN_SET; _nop_(); EN_CLR; } //写入数据,入口参数是要写入的数据 void LCD_Write_Data(unsigned char Data) { LCD_Check_Busy(); RS_SET; RW_CLR; DataPort=Data; EN_SET; _nop_(); EN_CLR; } //清屏函数 void LCD_Clear(void ) { LCD_Write_Com(0x01); DelayMs(5); } //LCD显示字符串,入口参数是 字符显示的位置X(0-15),显示的行数y(0,1 ),*S显示的字符串 void LCD_Write_String(unsigned char x,unsigned char y, unsigned char *s) { if(y==0) LCD_Write_Com(0x80+x); else LCD_Write_Com(0xc0+x); while(*s) { LCD_Write_Data(*s); s++; } } //LCD显示字符串,入口参数是 字符显示的位置X(0-15),显示的行数y(0,1 ),Data显示的字符 void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data) { if(y==0) LCD_Write_Com(0x80+x); else LCD_Write_Com(0xc0+x); DelayMs(1);//a little delay for simulation LCD_Write_Data(Data); } //lcd初始化函数 void LCD_Init(void) { LCD_Write_Com(0x38);// set the display model DelayMs(5); LCD_Write_Com(0x08);//turn down the display //LCD_Write_Com(0x01);//clear the display LCD_Clear(); LCD_Write_Com(0x06);//set the 光标 moving model DelayMs(5); LCD_Write_Com(0x0c);//显示开和光标设置 } /**************************************** 用于显示的数位分解函数,把数据转化为ASCII码 入口参数是要显示的数据 ****************************************/ void DepartNum(unsigned int temp) { qian=temp/1000+0x30; bai=temp%1000/100+0x30; shi=temp%100/10+0x30; ge= temp%10+0x30; } void ISIR_INT0(void) interrupt 0 { unsigned int PPM_temp; if(TR0) { TR0=0;//停止计数; PPM_temp=TH0; PPM_temp=(PPM_temp<<8)|TL0; TH0=0; TL0=0; TR0=1;//给TH0和TL0赋初值后重新启动定时器 } else { TH0=0;//如果是第一次启动中断,则启动timer0 TL0=0; TR0=1; } if(PPM_temp>3000|| Timer0_OverFlowFlag)//判断引导区 { channel=0; Timer0_OverFlowFlag=0; i++; if(i==10) i=0; } switch(channel) { case 1: PPM_channel1[i]=PPM_temp; break; case 2: PPM_channel2[i]=PPM_temp; break; case 3: PPM_channel3[i]=PPM_temp; break; case 4: PPM_channel4[i]=PPM_temp; break; case 5: PPM_channel5[i]=PPM_temp; break; case 6: PPM_channel6[i]=PPM_temp; break; case 7: break; case 8: break; default:break; } channel++; } void ISIR_Timer0(void) interrupt 1 { Timer0_OverFlowFlag=1; } unsigned int filter(unsigned int *s) { unsigned char k,j; unsigned int sum=0; unsigned int temp; for(k=0;k<9;k++) for(j=k+1;j<10;j++) if(s[k]>s[j]) { temp=s[k]; s[k]=s[j]; s[j]=temp; } for(k=1;k<9;k++) sum+=s[k]; sum=sum/8; return sum; }