找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2763|回复: 0
收起左侧

关于51单片机采样问题

[复制链接]
ID:51758 发表于 2013-8-5 15:35 | 显示全部楼层 |阅读模式
问题概述如下:我要用51单片机采样外部的红外信号数据,用定时器0定时26us进行采样,然后将采样的数值存入数组,但现在发现采样出来的数值和理论值差距有点大,比如说理论值是0.56ms,采样出来的值有可能只有0.30ms,这个问题出在哪里?
代码如下:#include<reg52.h>
#include<intrins.h>

typedef unsigned int uint;
typedef unsigned char uchar;
sbit  Txd_Port = P1^0;                         //发射脚
sbit remotein = P3^2;                        //遥控信号输入口
sbit Txd_key = P1^1;                    //发射键
sbit Txd_key1 = P1^2;                        //发射键2
sbit scl = P3^6;                //I2C时钟信号线
sbit sda = P3^7;                                //I2C数据线
unsigned short data count1 = 0;
uchar idata remotedata[80];                   //存脉冲宽度数据用         数组较大,放在idata里 ,只能用指针读写
uchar int_flag = 0;                                        // 红外接收中断是否产生
uchar Time1_Flag = 0;


sbit test0 = P0^0;
sbit test1 = P0^1;
sbit test2 = P0^2;
sbit test3 = P0^3;
sbit test4 = P0^4;
sbit test5 = P0^5;
sbit test6 = P0^6;
sbit test7 = P0^7;

/***************************************
延时2个_nop_
***************************************/
void flash(void)
{
        _nop_();
        _nop_();
}
/**************************************
Delay_1ms   延时1MS

**************************************/
void Delay_1ms(uint i)
{
        uint x, j;
        for(j=0; j<i; j++)
        for(x=0; x<=148; x++)
        ;       
}
/********************************************************************
* 名称 : x24c02_init()
* 功能 : 24c02初始化子程序
* 输入 : 无
* 输出 : 无
***********************************************************************/
void x24c02_init(void)
{
        scl = 1;
        flash();
        sda = 1;
        flash();
}

/********************************************************************
* 名称 : start(void)
* 功能 : 启动I2C总线
* 输入 : 无
* 输出 : 无
***********************************************************************/
void start(void)
{
        scl = 1;
        flash();
        sda = 1;
        flash();
        sda = 0;
        flash();
        scl = 0;
        flash();
}

/********************************************************************
* 名称 : stop()
* 功能 : 停止I2C总线
* 输入 : 无
* 输出 : 无
***********************************************************************/
void stop()
{
        scl = 0;
        flash();
        sda = 0;
        flash();
        scl = 1;
        flash();
        sda = 1;
        flash();
}

/********************************************************************
* 名称 : writex()
* 功能 : 写一个字节
* 输入 : j(需要写入的值)
* 输出 : 无
***********************************************************************/
void writex(uchar j)
{  
        uchar i,temp;
        temp = j;
        for(i=0; i<8; i++)
        {
                scl = 0;
                flash();
                sda = (bit)(temp & 0x80);
                flash();
                scl = 1;
                flash();
                temp = temp << 1;
        }
        scl = 0;
        flash();
}

/********************************************************************
* 名称 : readx()
* 功能 : 读一个字节
* 输入 : 无
* 输出 : 读出的值
***********************************************************************/
uchar readx(void)
{
        uchar i, j, k = 0;
        for(i=0; i<8; i++)
        {
                scl = 1;
                flash();               
                if(sda == 1)
                {
                        j = 1;
                }
                else j = 0;
                k = (k << 1) | j;
                scl = 0;
                flash();
        }
        return(k);
}

/********************************************************************
* 名称 : ack()
* 功能 : I2C总线时钟
* 输入 : 无
* 输出 : 无
***********************************************************************/
void ack(void)
{
        scl = 1;
        flash();
        flash();
        scl = 0;
        flash();
}

/********************************************************************
* 名称 : x24c02_read()
* 功能 : 从24c02中读出值
* 输入 : address(要在这个地址读取值)
* 输出 : 从24c02中读出的值
***********************************************************************/
uchar x24c02_read(uchar address)
{
        uchar i;
        start();
        writex(0xa0);
        ack();
        writex(address);
        ack();
        start();
        writex(0xa1);
        ack();
        i = readx();
        sda = 1;           //no ack
        ack();
        stop();
        return(i);
}

/********************************************************************
* 名称 : x24c02_write()
* 功能 : 想24c02中写入数据
* 输入 : address(地址) , info(值)
* 输出 : 无
***********************************************************************/
void x24c02_write(uchar address, uchar info)
{
        start();
        writex(0xa0);
        ack();
        writex(address);
        ack();
        writex(info);
        ack();
        stop();
}


/**************************************
函数名称:矩阵键盘
用法:矩阵端口接P2口
***************************************/
int Detect_key_down(void)                  
{
        uchar temp = 0x00;
        P2 = 0xfe;
        temp = P2;
        switch (temp) {
                case 0xee: return 0;
                case 0xde: return 1;
                case 0xbe: return 2;
                case 0x7e: return 3;
                default: break;
        }
        P2 = 0xfd;
        temp = P2;
        switch (temp) {
                case 0xed: return 4;
                case 0xdd: return 5;
                case 0xbd: return 6;
                case 0x7d: return 7;
                default: break;
        }
        P2 = 0Xfb;
        temp = P2;
                switch (temp) {
                case 0xeb: return 8;
                case 0xdb: return 9;
                case 0xbb: return 10;
                case 0x7b: return 11;
                default: break;
        }
        P2 = 0Xf7;
        temp = P2;
        switch (temp) {
                case 0xe7: return 12;
                case 0xd7: return 13;
                case 0xb7: return 14;
                case 0x77: return 15;
                default: break;
        }
        return 16;
} //end  KEY
/**************************************
函数功能:红外线产生中断函数
用法:红外线接收口接P3^2
****************************************/
void IR_RexFlag()  interrupt  0                                    
{
        EX0 = 0;
        int_flag = 1;
        TR0 = 1;
        count1 = 0;                                           //开定时器0   26us
}
void Time0_init()
{
        TH0 = 0Xe7;                           //38KHz载波    26us
        TL0 = 0Xe7;
        ET0 = 1;              //开中断
}
void  Time0_26us() interrupt 1
{
         Txd_Port = 1;
         TR1 = 1;
         count1++;
         test4 = 0;
}
void Time1_init()
{
        TH1 = 0Xf9;                           //8us
        TL1 = 0Xf9;
        //ET1 = 1;
}
void Time1_9us() interrupt 3
{
        TR1 = 0;              //关定时器
        Txd_Port = Time1_Flag;
        test3 = 0;
}
void TR0_Count(unsigned short count)                   //26us*count,有信号
{
        Time1_Flag = 0;
        count1 = 0;
        TR0 = 1;
        while(count1<count);
        TR0 = 0;
}
void TR0_Count1(unsigned short count)
{                                                                                          //26*count,无信号
        Time1_Flag = 1;
        count1 = 0;
        TR0 = 1;
        while(count1<count);
        TR0 = 0;
}
void Com_Init(void)                                                                //串口打印初始化
{
     TMOD = 0x20;
     PCON = 0x00;
     SCON = 0x50;                       
     TH1 = 0xFd;
     TL1 = 0xFd;
     TR1 = 1;                       
}
int main(void)
{
        uchar count_flag = 0;       
        uchar IR_First = 0;                    //红外线接收开启中断标志
        uchar key_again = 0;                                  //按第二个按键的其实条件
        char n_elements = 80;
        uint data1 = 0;                       //记录数组里面的数据
        uchar *P = 0;                                                //将idata的数组存到E2PROM里面
        //uchar sec = 0;                                                //数组元素
        uchar last_in = 0;                                          // 默认输入为低电平
        uchar key_value;                                        //存放按键值
//        uchar close_T0 = 0;
        uchar key_down_flag = 0;                        //按键抬起的标记(按键已经按下过了)
        uchar *pArray = 0;                                           //接收指针
        unsigned short *pArray1 = 0;
        uchar *PTex = 0;                                          //发射指针
        unsigned short *PTex1 = 0;
        uchar *PE = &remotedata[0];                        //数组存入E2PROM的指针
        uchar up_down = 0;                                                                //标记红外线的9MS低电平,4.5MS高电平的引导码
        uchar Key_down = 1;
        uchar i = 0;
        uchar j = 0;
        uchar k = 0;
        unsigned short remoteout = 0;

        //for(i=0;i<80;i++)           //清空数组内存
        //{
        //        remotedata[i] = 0x00;
        //}
        x24c02_init();                //初始化I2C总线

        test0 = 1;
        test1 = 1;
        test2 = 1;
        test3 = 1;
        test4 = 1;
        test5 = 1;
        test6 = 1;
        test7 = 1;


          EA = 1;
          TMOD = 0X22;              //8位自动重装
        IT0 = 1;                                  //脉冲触发方式,负跳变有效
          Time0_init();
          Time1_init();


        while(1)
        {
                key_value = Detect_key_down();
                if (key_value == 16)
                {        // 没有按键按下,或者按键已经UP
                       
                    if (key_down_flag == 1)       
                        {                 // 按键1抬起       
                                P = &remotedata[0];
                                for(i=0;i<80;i++)                                 //数组写入E2PROM
                                {
                                        x24c02_write(i,*P);
                                        P++;
                                        Delay_1ms(5);                                          //每一次写数据后要进入E2PROM内部写周期,最大时长为5ms
                                }
                                 key_down_flag = 0;
                                    IR_First = 0;
                                //TR1 = 0;
                        //        if(close_T0 == 0)
                        //        {
                        //                TR0 = 0;        //        关定时器0
                        //                TR1 = 0;
                        //                close_T0 = 1;
                        //        }
                                //PTex = &remotedata[0];
                                //PTex1 = (unsigned short*)&remotedata[0];
                        }       
                        if(key_down_flag == 2)
                        {        //如果按键2抬起
                                P = &remotedata[0];
                                for(i=80;i<160;i++)                                 //数组写入E2PROM
                                {
                                        x24c02_write(i,*P);
                                        P++;
                                        Delay_1ms(5);
                                        test0 = 0;                                          //每一次写数据后要进入E2PROM内部,写周期最大时长为5ms
                                }
                                 key_down_flag = 0;
                                //int_flag = 0;                         //红外线标志
                                //last_in = 0;                                         //高低电平翻转标志
                                //up_down = 0;                                         //9ms,4.5ms判断标志
                                //pArray = &remotedata[0];
                                //pArray1 = (unsigned short*)&remotedata[0];
                                //TR0 = 0;                                                  //一次接收完成以后定时器关闭
                                //TR1 = 0;
                        }
                               


                                if(Txd_key == 0)
                                  {
                                        PE = &remotedata[0];
                                        Com_Init();
                                        while(Txd_key ==0);
                                        for(i=0;i<80;i++)
                                        {
                                                *PE= x24c02_read(i);                                          
                                                SBUF = *PE;
                                           while(!TI)
                                           {
                                                           ;
                                           }
                                           TI = 0;
                                          // Delay_1ms(5);
                                           PE++;
                                        }
                                }
                                if(Txd_key1 == 0)
                                 {
                                        PE = &remotedata[0];
                                        Com_Init();
                                        while(Txd_key1 ==0 );
                                        for(i=0;i<80;i++)
                                        {
                                                *PE        = x24c02_read(80+i);                                          
                                                SBUF = *PE;
                                                  while(!TI)
                                                  {
                                                           ;
                                                  }
                                                  TI = 0;
                                                  Delay_1ms(5);
                                                  PE++;
                                        }
                                }                                                
                                 
                /*        if(Txd_key == 0)                           //发射0键按下         
                        {
                                PE = &remotedata[0];
                                for(i=0;i<80;i++)
                                {
                                        *PE++ = x24c02_read(i);
                                //        remotedata[i] = x24c02_read(i);
                                }
                                ET1 = 1;               //开启定时器1中断    接收的时候不用定时器1;
                                PTex = &remotedata[0];
                                PTex1 = (unsigned short*)&remotedata[0];
                                data1 = (*PTex1);
                                TR0_Count(data1);           //9MS低电平
                                PTex1++;
                                data1 = (*PTex1);           //4.5MS高电平
                                TR0_Count1(data1);
                                PTex1++;
                                PTex = (uchar*)PTex1;
                                test0 = 0;

                                for(j=0;j<n_elements-4;j++)
                                {
                                        data1 = (*PTex);
                                        TR0_Count(data1);          //发信号
                                        PTex++;
                                        data1 = (*PTex);          
                                        TR0_Count1(data1);          //不发信号
                                        PTex++;
                                        test1 = 0;
                                        if(*PTex == 0)
                                        {
                                                Txd_Port = 1;
                                                test2 = 0;
                                        }
                                }
                                TR0_Count1(200);                                        //两组数据之间50ms的时间间隔
                        }
                        if(Txd_key1 == 0)                           //发射键1按下         
                        {
                                PE = &remotedata[0];
                                for(i=0;i<80;i++)
                                {
                                        *PE++ = x24c02_read(i+80);
                                //        remotedata[i] = x24c02_read(i);
                                }
                        //        ET1 = 1;               //开启定时器1中断    接收的时候不用定时器1;
                                PTex = &remotedata[0];
                                PTex1 = (unsigned short*)&remotedata[0];
                                data1 = (*PTex1);
                                TR0_Count(data1);           //9MS低电平
                                PTex1++;
                                data1 = (*PTex1);           //4.5MS高电平
                                TR0_Count1(data1);
                                PTex1++;
                                PTex = (uchar*)PTex1;
                                test0 = 0;

                                for(j=0;j<n_elements-4;j++)
                                {
                                        data1 = (*PTex);
                                        TR0_Count(data1);          //发信号
                                        PTex++;
                                        data1 = (*PTex);          
                                        TR0_Count1(data1);          //不发信号
                                        PTex++;
                                        test1 = 0;
                                        if(*PTex == 0)
                                        {
                                                Txd_Port = 1;
                                                test2 = 0;
                                        }
                                }
                                TR0_Count1(200);                                        //两组数据之间50ms的时间间隔
                        }                                        */       
                        //key_down_flag = 0;               
                        IE0 = 0;                                                         //当按键还没有按下的时候不能产生中断                       
                }
                 else                                                                   //接受模块
                 {
                        if (key_value == 0)
                        {
                                if(IR_First == 0)                  //每次红外线到来时就开一次中断
                                 {
                                        pArray = &remotedata[0];
                                        pArray1 = (unsigned short*)&remotedata[0];
                                        EX0 = 1;                         //开外中断0;
                                        IR_First++;
                                }
                                if (key_down_flag == 0)
                                {
                                        key_down_flag = 1;
                                }                           
                            if (int_flag == 1)                                   // 有数据传送
                            {       
                                        if (remotein == 0)                           //如果是低电平
                                        {
                                                if (last_in == 1)                  //等待它翻转成高电平
                                                {                                 
                                                        if (up_down == 1)        //如果是第一次           4.5MS
                                                        {                 
                                                                *pArray1++ = count1;
                                                                 pArray = (unsigned char*)pArray1;
                                                                 count1 = 0;
                                                                 up_down++;
                                                        }
                                                        else
                                                    {       
                                                                *pArray++ = count1;          
                                                                count1 = 0;
                                                           }
                                                        last_in = 0;
                                                }
                                        }
                                        else
                                        {
                                                if (last_in == 0)
                                                {
                                                        // 9MS
                                                        if (up_down == 0)
                                                        {                
                                                                *pArray1++ = count1;
                                                                 //pArray = (unsigned char*)pArray1;
                                                                 count1 = 0;
                                                                 up_down++;
                                                        }
                                                        else
                                                        {       
                                                                *pArray++ = count1;
                                                                count1 = 0;
                                                        }
                                                        last_in = 1;
                                                }
                                    }
                            }
                        }
                         
                        if (key_value == 1)
                        {
                                if(IR_First == 0)
                                {
                                        int_flag = 0;                         //红外线标志
                                        last_in = 0;                                         //高低电平翻转标志
                                        up_down = 0;                                         //9ms,4.5ms判断标志
                                        pArray = &remotedata[0];
                                        pArray1 = (unsigned short*)&remotedata[0];

                                        //TR0 = 0;                                                  //一次接收完成以后定时器关闭
                                        test1 = 0;
                                        //TR0 = 0;
                                        //TR1 = 0;
                                        EX0 = 1;  
                                        Time0_init();
                                          //Time1_init();
                                        IR_First ++;
                                }
                                if (key_down_flag == 0)
                                {
                                        key_down_flag = 2;
                                        test2 = 0;
                                }                                          
                                   if (int_flag == 1)                   // 有数据传送
                                   {       
                                        if (remotein == 0)           //如果是低电平
                                        {
                                                if (last_in == 1)  //等待它翻转成高电平
                                                {                                 
                                                        if (up_down == 1)        //如果是第一次           4.5MS
                                                        {                 
                                                                *pArray1++ = count1;
                                                                 pArray = (unsigned char*)pArray1;
                                                                 test3 = 0;
                                                                 count1 = 0;
                                                                 up_down++;
                                                        }
                                                        else
                                                    {       
                                                                *pArray++ = count1;          
                                                                count1 = 0;
                                                                test7 = 0;
                                                           }
                                                        last_in = 0;
                                                }
                                        }
                                        else
                                        {
                                                if (last_in == 0)
                                                {
                                                        // 9MS
                                                        if (up_down == 0)
                                                        {                
                                                                *pArray1++ = count1;
                                                                // pArray = (unsigned char*)pArray1;
                                                                 count1 = 0;
                                                                 up_down++;
                                                                 test5 = 0;
                                                        }
                                                        else
                                                        {       
                                                                *pArray++ = count1;
                                                                count1 = 0;
                                                                test6 = 0;
                                                        }
                                                        last_in = 1;
                                                }
                                    }
                            }
                        }
                }
        }                       
        return 0;
}

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表