单片机解码

时间:2024-03-04 20:30:44编辑:奇闻君

如何用单片机实现FSK来电显示解码

  一、nbsp;来电号码显示技术的基本原理nbsp;来电号码显示实际上是现代电信交换网络可以提供的一项服务业务。就其机理而言,是指交换机对用户提供来电号码专用格式的数据的传送,而用户终端利nbsp;用符合数据解码格式要求的端机进行接收和显示。当交换机发出第一次振铃信号后,紧接着发出一串调制信号(现用的主要有FSK和DTMF两种格式的信号),nbsp;此信号包含着拨号方的电话号码、日期、时间、姓名等信息。来电号码显示器在每一次振铃信号的唤醒下,开始接收FSK信号,经解码芯片(如Motorolanbsp;的RC145447)获得其中信息,由单片机进行格式处理并在屏幕上显示出来。同样,若传输过来的是DTMF来电号码信息,只需由DTMF解码芯片来进行nbsp;数据解码,即可显示DTMF的来电号码。nbsp;二、nbsp;电路原理及设计nbsp;本文介绍的来电号码显示器以MC68HC05P1为主控单片机,控制MC145447接收符合Bell202标准的FSK信号。其中,单制式信息包括日期、时间、电话号码;复合制式信息包括日期、时间、电话号码、姓名。来电显示器可存储60个记录。nbsp;1.nbsp;主要功能介绍nbsp;该机的主要功能有如下五个方面。nbsp;1)nbsp;一般Callnbsp;ID接收显示功。Callnbsp;ID平时处于等待状态,当电话振铃时被唤醒,进入接收状态。LCD开始显示接收到的信息。nbsp;2)nbsp;长途电话或私人电话批示功能。当Callnbsp;ID接收到长途电话或私人电话时,电话号码空缺,屏幕上显示Outnbsp;ofnbsp;Areanbsp;(长途电话)或Private(私人电话)。nbsp;3)nbsp;Mailnbsp;Box指示功能。当电信局开通Mailnbsp;Box服务项目时,Callernbsp;ID能显示“Mailnbsp;Box”表示有留言。nbsp;4)nbsp;重要号码报警功能。接收到的信息与存储器中被设置成重要号码的记录相同时,Callnbsp;ID会发出报警音,提醒用户接听电话。nbsp;5)nbsp;厌恶电话的过滤功能。接收到的信息与存储器中被设置成厌恶号码的记录相同时,Callnbsp;ID会自动模拟提机2S再挂机,使对方电话打不进来。nbsp;从图中可见TI-RI为外接电话线;MC68HC05P1为主控单片机,用于控制信号的接收,信息的显示、存储,以及数据显示格式的轮换等;nbsp;MC145447为FSK信号的接收解码芯片;LCD202为2行╳20字符LCD显示屏;U4(24C16)为E2PROM存储器;系统使用+5V直流nbsp;电源工作。nbsp;当振铃信号从TI-RI输入到MC145447解芯片时,即产生中断信号,唤醒MC68HC05P1单片机。解码芯片接收FSK信号进行解码,nbsp;单片机读取中期数据进行格式处理,并开启LCD显示屏,同时也接通EEPROM存储器的电源。单片机从EEPROM存储器中读取存储的电话号码,与刚接收nbsp;到的信息进行比较,判断其性质,然后把结果及电话号码等信息显示在LCD显示屏上,并存储修改EEPROM存储器的内容。nbsp;3.nbsp;程序设计流程nbsp;接收显示的程序主要以中断服务方式进行,其流程原理如nbsp;三、nbsp;使用方法nbsp;Callernbsp;IDnbsp;来电号码显示器作为电话伴侣,与电话机简单并接即可使用,不会影响电话机的正常使用。其采用9V干电池或9——12V直流充电器供电。Calerlnbsp;ID正常工作电流为6.8nbsp;mnbsp;A,等待状态耗电极微,如使用9V干电池供电,可连续使用3-6个月。nbsp;本文介绍的来电号码显示器是单制式的,另一种同时可处理、显示不同制式的来电号码显示器正进一步开发之中。其实Callernbsp;IDnbsp;也可以与电话机合为一体,使用同一单片机和显示屏,使电话机的功能更强。


51单片机红外线解码的程序

实际上如果ir_code[2]是8位二进制数的话 ir_code[2]/16,结果就只剩低4 位有效了
再进行&0x0f;还是取低4位没意义了 如 0XA8/16=0X0A 0X0A &0x0f=0X0A
ir_code[2]&0x0f有意义 是 将高4位清0只取低4位
估计你的表格里只有16个七段码 因此查表时只能对高4位和低4位(都不大于15)分别处理和显示
/16和数学的除法相似,不过只取整数部分,不理会余数 如 15/16=0 17/16=1 18/16=1
32/16=2 35/16=2
0x0f化成二进制是 0000 1111 另一个二进制数xxxx xxxx和它相“与” 则高4位全为0
低4位不变,即(xxxx xxxx)&(0000 1111 )=0000 xxxx
另外,/2相当于把这个二进制数向右移1 位(高位补0)
/4相当于把这个二进制数向右移2 位
/16相当于把这个二进制数向右移4 位,原来的高4位就跑到了现在的低4 位上,现在高4 位就全成了0
所以C 语言中常见>>4 >>8 和/16 /256是等价的


51单片机红外解码C程序

单片机采用外部中断P3.3管脚和红外接收头的信号线相连,中断方式为边沿触发方式。并用定时器0计算中断的间隔时间,来区分前导码、二进制的“1”、“0”码。并将8位操作码提取出来在数码管上显示。// 解码值在Im[2]中,当IrOK=1时解码有效。 /* 51单片机红外遥控解码程序 *///用遥控器对准红外接收头,按下遥控器按键,在数码管前两位上就会显示对应按键的编码#include #define uchar unsigned char sbit dula=P2^6;sbit wela=P2^7;uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,                        0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};uchar f;#define Imax 14000    //此处为晶振为11.0592时的取值, #define Imin 8000    //如用其它频率的晶振时,#define Inum1 1450    //要改变相应的取值。#define Inum2 700 #define Inum3 3000unsigned char Im[4]={0x00,0x00,0x00,0x00};uchar show[2]={0,0};unsigned long m,Tc;unsigned char IrOK;void delay(uchar i){  uchar j,k;   for(j=i;j>0;j--)    for(k=125;k>0;k--);}void display(){   dula=0;   P0=table[show[0]];   dula=1;   dula=0;   wela=0;   P0=0xfe;   wela=1;   wela=0;   delay(5);   P0=table[show[1]];   dula=1;   dula=0;   P0=0xfd;   wela=1;   wela=0;   delay(5);} //外部中断解码程序void intersvr1(void) interrupt 2 using 1{ Tc=TH0*256+TL0;                                               //提取中断时间间隔时长 TH0=0;     TL0=0;              //定时中断重新置零 if((Tc>Imin)&&(Tc<Imax))      {   m=0;        f=1;  return;      }       //找到启始码   if(f==1)      {        if(Tc>Inum1&&Tc<Inum3)     {   Im[m/8]=Im[m/8]>>1|0x80; m++;        }      if(Tc>Inum2&&Tc<Inum1)         {         Im[m/8]=Im[m/8]>>1; m++; //取码  }  if(m==32)    {         m=0;           f=0;         if(Im[2]==~Im[3])       {           IrOK=1;    }        else IrOK=0;   //取码完成后判断读码是否正确     }               //准备读下一码   }}/*演示主程序*/void main(void){    unsigned int  a; m=0;    f=0; EA=1; IT1=1;EX1=1; TMOD=0x11;   TH0=0;TL0=0; TR0=1;//ET0=1; while(1) {       if(IrOK==1)   {      show[1]=Im[2] & 0x0F;     //取键码的低四位           show[0]=Im[2] >> 4;             IrOK=0;  }           for(a=100;a>0;a--)          {    display();   } }}解码程序这个就能实现


关于单片机的问题(红外遥控解码程序问题)

这个我不太熟悉,我只能就程序本身来说
void interrupt_ISR() interrupt 0
{
EX0=0; //D is able INT 0
TR0=0; //D is able Timer0
IRint=1;
//为什么要把IRint置1(IRint接MCU单片机 P3^2)
这个问题你不应该问我,应该看说明的
interval=TH0;
TH0=0xb0; //怎么算得TH0的值?
0x起头的数字是16进制数,THO=b*16=176(十进制)
TL0=0;
TR0=1; //Enable Timer0
EX0=1; //Enable INT0
}


bit IRdecode()
{
static Idata BYTE INTcount=0;
//这里可以用uchar INTcount;INTcount=0;代替吗?
其实这个你最好自己调试一下就知道行不行了,后面的操作主要是
比较大小,uchar比较的时候一般是会自动进行数字比较的,但是在单片机
上就不清楚了,可能支持不是那么好,这个最好按规范的写法来。
static ulong idata IRdata=0;
BYTE IRdata1,IRdata2,IRdata3,IRdata4;
if(IRint)
{
if((interval>0xde)&&(interval<0xe1)) //0xdfe2=13.5ms
{
IRdata=0;
INTcount=0;
}
else if((interval>0xb6)&&(interval<0xb9)) //0xb7fb=2.25ms(data=1)
{
IRdata=(IRdata<<1)+1;
INTcount++;
}
else if((interval>0xb2)&&(interval<0xb5)) //0xb3fd=1.125ms(data=0)
{
IRdata=IRdata<<1;
INTcount++;
}
else if((interval>0xd6)&&(interval<0xd9)) //0xd7e7=11.25ms
{
IRint=0;
IRdata=0;
IRcommanddata=0xff;
//repeat重复 code flag有什么意义吗? 没明白你的意思
return 1; 返回1值到哪去? 返回值见下面
}
else
{
INTcount=33;
IRdata=0;
}
IRint=0;
if(INTcount==32)
{
IRdata1=(BYTE)(IRdata>>24);
//这部分是什么意思,有什么作用?
前面(BYTE)是强行转换(IRdata>>24)的结果为BYTE型,>>是右移运算,按二进制计算的,例如1111000》1=0111100 左边补0
IRdata2=(BYTE)(IRdata>>16);
IRdata3=(BYTE)(IRdata>>8);
IRdata4=(BYTE)(IRdata);
IRdata=0;
if(IRdata4==~IRdata3)
{
IRcommanddata=IRdata3; //还原命令成功
return 1;
}
else
return 0;
}
else
return 0;
}
return 0; 返回值0给谁??

return当然是返回个调用者,调用函数之前并不存在实际的返回者,
例如bit a=IRdecode()
无论返回1还是0都是返回给a.在这行代码里a就是调用者
}



#include
void main()
{
TH0=0XB0;
EA=0;
ET0=1; //Enable Timer0 interrupt
TMOD=0x21;//定时器0,工作模式1;定时器1,工作模式2(8位自动重装) 为什么要启用两个定时器??

这个你更应该看看说明书,每个开发板的用法都不同
TCON=0x50; //TR0=TR1=1,start timers
EA=1;
while(1)
{
}
貌似你MAIN函数里没有调用过上面的函数
}


怎样用51单片机定时器点亮一个led灯

sbit LED =P1^0;//定义LED管脚
uchar a=0;//计中断次数的变量
void main(void)
{
TMOD=0x10; //定时器1工作在定时方式1
TH1=(65536-50000)/256; //定时50毫秒
TL1=(65536-50000)%256;
ET1=1;EA=1;
TR1=1;
while(1);
}
void timer1(void) interrupt 3//中断子程序
{
TH1=(65536-50000)/256; //定时50毫秒
TL1=(65536-50000)%256;
a++;
if(a==20){a=0;LED=!LED;}//20次是1s LED亮灭
}


单片机红外解码

红外解码程序!

/*-----------------------------------------------
名称:遥控器红外解码液晶显示
------------------------------------------------*/
#include //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include
#include


#define TURE 1
#define FALSE 0


sbit IR=P3^2; //红外接口标志
sbit RS = P2^4;//Pin4
sbit RW = P2^5;//Pin5
sbit E = P2^6;//Pin6

#define Data P0//数据端口

unsigned int hour,minute,second,count;
char code Tab[16]="0123456789ABCDEF";

char data TimeNum[]=" ";
char data Test1[]=" ";

/******************************************************************/
/* 变量声明 */
/******************************************************************/

unsigned char irtime;//红外用全局变量

bit irpro_ok,irok;
unsigned char IRcord[4]; //处理后的红外码,分别是 客户码,客户码,数据码,数据码反码
unsigned char irdata[33]; //33个高低电平的时间数据

/******************************************************************/
/* 函数声明 */
/******************************************************************/
void Ir_work(void);
void Ircordpro(void);
void ShowString (unsigned char line,char *ptr);
/******************************************************************/
/* 定时器0中断服务函数 */
/******************************************************************/

void tim0_isr (void) interrupt 1 using 1//定时器0中断服务函数
{
irtime++; //用于计数2个下降沿之间的时间
}

/******************************************************************/
/* 外部中断0函数 */
/******************************************************************/
void ex0_isr (void) interrupt 0 using 0//外部中断0服务函数
{
static unsigned char i; //接收红外信号处理
static bit startflag; //是否开始处理标志位

if(startflag)
{

if(irtime=33)//引导码 TC9012的头码,9ms+4.5ms
i=0;

irdata[i]=irtime;//存储每个电平的持续时间,用于以后判断是0还是1
irtime=0;
i++;
if(i==33)
{
irok=1;
i=0;
}
}

else
{irtime=0;startflag=1;}

}

/******************************************************************/
/* 定时器0初始化 */
/******************************************************************/
void TIM0init(void)//定时器0初始化
{

TMOD=0x02;//定时器0工作方式2,TH0是重装值,TL0是初值
TH0=0x00; //重载值
TL0=0x00; //初始化值
ET0=1; //开中断
TR0=1;
}
/******************************************************************/
/* 外部中断初始化 */
/******************************************************************/
void EX0init(void)
{
IT0 = 1; //指定外部中断0下降沿触发,INT0 (P3.2)
EX0 = 1; //使能外部中断
EA = 1; //开总中断
}
/******************************************************************/
/* 红外键值处理 */
/******************************************************************/

void Ir_work(void) //红外键值散转程序
{

TimeNum[5] = Tab[IRcord[0]/16]; //处理客户码并显示
TimeNum[6] = Tab[IRcord[0]%16];
TimeNum[8] = Tab[IRcord[1]/16]; //处理客户码并显示
TimeNum[9] = Tab[IRcord[1]%16];
TimeNum[11] = Tab[IRcord[2]/16]; //处理数据码并显示
TimeNum[12] = Tab[IRcord[2]%16];
TimeNum[14] = Tab[IRcord[3]/16]; //处理数据反码并显示
TimeNum[15] = Tab[IRcord[3]%16];

ShowString(1,TimeNum);//显示处理过后的码值
irpro_ok=0; //处理完成后清楚标志位

}

/******************************************************************/
/* 红外解码函数处理 */
/******************************************************************/
void Ircordpro(void)//红外码值处理函数
{
unsigned char i, j, k;
unsigned char cord,value;

k=1;
for(i=0;i<4;i++) //处理4个字节
{
for(j=1;j<=8;j++) //处理1个字节8位
{
cord=irdata[k];
if(cord>7)//大于某值为1,这个和晶振有绝对关系,这里使用12M计算,此值可以有一定误差
{
value=value|0x80;
}
else
{
value=value;
}
if(j<8)
{
value=value>>1;
}
k++;
}
IRcord[i]=value;
value=0;
} irpro_ok=1;//处理完毕标志位置1

}


/******************************************************************/
/* 微秒延时函数 */
/******************************************************************/
void DelayUs(unsigned char us)//delay us
{
unsigned char uscnt;
uscnt=us>>1;/* Crystal frequency in 12MHz*/
while(--uscnt);
}
/******************************************************************/
/* 毫秒函数声明 */
/******************************************************************/
void DelayMs(unsigned char ms)//delay Ms
{
while(--ms)
{
DelayUs(250);
DelayUs(250);
DelayUs(250);
DelayUs(250);
}
}

/******************************************************************/
/* 写入命令函数 */
/******************************************************************/
void WriteCommand(unsigned char c)
{
DelayMs(5);//操作前短暂延时,保证信号稳定
E=0;
RS=0;
RW=0;
_nop_();
E=1;
Data=c;
E=0;
}
/******************************************************************/
/* 写入数据函数 */
/******************************************************************/
void WriteData(unsigned char c)
{
DelayMs(5); //操作前短暂延时,保证信号稳定
E=0;
RS=1;
RW=0;
_nop_();
E=1;
Data=c;
E=0;
RS=0;
}
/******************************************************************/
/* 写入字节函数 */
/******************************************************************/
void ShowChar(unsigned char pos,unsigned char c)
{
unsigned char p;
if (pos>=0x10)
p=pos+0xb0; //是第二行则命令代码高4位为0xc
else
p=pos+0x80; //是第二行则命令代码高4位为0x8
WriteCommand (p);//写命令
WriteData (c); //写数据
}
/******************************************************************/
/* 写入字符串函数 */
/******************************************************************/
void ShowString (unsigned char line,char *ptr)
{
unsigned char l,i;
l=line<<4;
for (i=0;i<16;i++)
ShowChar (l++,*(ptr+i));//循环显示16个字符
}
/******************************************************************/
/* 初始化函数 */
/******************************************************************/
void InitLcd()
{
DelayMs(15);
WriteCommand(0x38); //display mode
WriteCommand(0x38); //display mode
WriteCommand(0x38); //display mode
WriteCommand(0x06); //显示光标移动位置
WriteCommand(0x0c); //显示开及光标设置
WriteCommand(0x01); //显示清屏

}


/******************************************************************/
/* 主函数 */
/******************************************************************/

void main(void)
{
EX0init(); //初始化外部中断
TIM0init();//初始化定时器

InitLcd(); //初始化液晶
DelayMs(15);

sprintf(Test1," haixiang MCU "); //显示第一行固定信息
ShowString(0,Test1);

sprintf(TimeNum,"Code ");//显示第二行固定信息
ShowString(1,TimeNum);


while(1)//主循环
{
if(irok) //如果接收好了进行红外处理
{
Ircordpro();
irok=0;
}

if(irpro_ok) //如果处理好后进行工作处理,如按对应的按键后显示对应的数字等
{
Ir_work();
}
}
}


单片机外部中断和定时器冲突了?帮忙看看程序~外部中断有几率使定时器停止工作或不再中断

首先你的Timer1是模式0(13位计数器),除非用很低频率的外部晶体,否则Timer1的定时时间根本就不是秒级。
其次你没有贴出 timerun 标志被修改的位置。如果你怀疑Timer1没有持续工作,可以暂时去掉if(timerun==1)条件,观察数码管是否每次都显示变化的值。
顺便说一句你的Timer0中断里面的语句效率低下,这不是一个健康的中断服务函数。中断服务函数是要力求简洁明快的。


有没有人用单片机做过FSK的软解码?

一般的话,用FPGA处理,也不会很难。
比较实用的是,用集成的FSK调制解调芯片,用单片机控制就可以了,像CMX469、CMX7143就是这一类的芯片。。CML公司是专门做数传集成芯片的,有兴趣可以到官网去看看:http://www.cmlmicro.com/

你想用单片机来做编解码,估计运算速度肯定跟不上的,还是直接用集成芯片好使,又稳定,避免麻烦事。如果真的要用软件实现,那么就用FPGA或者DSP吧


上一篇:第二届国际大米节

下一篇:魔法留学生5