|
本帖最后由 das 于 2015-4-5 00:36 编辑
- //*************************************************************************************//
- //--P3.4口采样过零信号,每10ms采样到一个过零高电平,用于PWM0的时钟信号--//
- //--P1.2口采样电位器的输出调光电压,并进行8bit的A/D转换--//
- /*P3.7口输出PWM信号,PWM信号的频率和相位角应该自动能根据P1.6口的过零信号和P1.2口的模拟信号,
- 进行计算分析,输出时实的控制信号,以控制可控硅的导通时间,达到调光的目的; */
- /*P3.2口利用外部中断功能,实现红外线遥控器的解码,以实现遥控功能. */
- //P1.6是AT24C01的数据端;P1.7是AT24C01的时钟端,用于存储红外摇器的解码值,达到记忆亮度的效果//
- //P1.0接LED指示灯//
- // 2013-9-13 /杨旭
- //*************************************************************************************//
- #include <stc12c2052ad.h>
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- sbit LED=P1^0;
- sbit IR_RE=P3^2;
- sbit SDA=P1^6; //AT24C01数据端
- sbit SCL=P1^7; //AT24C01时钟端
- //--------------------------------红外线解码用变量
- static uchar date[]={0,0,0,0};
- static uchar qinlong;
- //--------------------------------AD转换用变量
- static uchar AD_dat_over0,AD_dat_over1;
- static uchar j=0; //AD中断计数器
- //--------------------------------------------------------------------------/
- void delayms(uint a)
- {
- uint b;
- for(b=0;b<a;b++);
- }
- //--------------------------------------------------------------------------//
- void delay882()
- {
- uchar i,j;
- i=35;
- do{j=68;
- do{j--;}
- while(j);
- i--;
- }while(i);
- }
- //-------------------------
- void delay1000()
- {
- uchar i,j;
- i=39;
- do{j=70;
- do{j--;}
- while(j);
- i--;
- }while(i);
- }
- //-------------------------
- void delay2400()
- {
- uchar i,j;
- i=93;
- do{j=70;
- do{j--;}
- while(j);
- i--;
- }while(i);
- }
- //--------------------------------------------------------------------------//
- /*名称:初始化端口程序
- 功能:系统初始化,检测芯片运行
- */
- /*********************初始化LED程序******************************************/
- void int_LED(void) //LED闪烁3次表示初始化正常
- {
- uchar a;
- for(a=0;a<3;a++)
- {
- LED=0;
- delayms(1000);
- LED=1;
- }
- }
- //--------------------初始化端口程序-----------------------------------------/
- void int_cushi(void)
- {
- P1=1;
- P3=1;
- int_LED();
- }
- //--------------------------------------------------------------------------//
- /*名称:EEROM通信程序
- 功能:完成摸拟I2C功能,完成AT24C01的读和写操作
- */
- //----------
- void delay()
- { ; ; }
- //----------
- void start()//启始信号
- {
- SDA=1;
- delay();
- SCL=1;
- delay();
- SDA=0;
- delay();
- }
- //----------
- void stop()//终止信号
- {
- SDA=0;
- delay();
- SCL=1;
- delay();
- SDA=1;
- delay();
- }
- //----------
- void respons() //应答信号,等待或者发送一个应答信号
- {
- uchar i;
- SCL=1;
- delay();
- while((SDA==1)&&(i<250))i++;
- SCL=0;
- delay();
- }
- //----------
- void I2C_init()//初始化
- {
- SDA=1;
- SCL=1;
- }
- //----------
- void write_byte(uchar date)//写一字节
- {
- uchar i;
- SCL=0;
- for(i=0;i<8;i++)
- {
- date=date<<1;
- SDA=CY;
- SCL=1;
- delay();
- SCL=0;
- delay();
- }
- }
- //----------
- uchar read_byte() //读数据(也就是接收从器件传来的数据)
- {
- uchar i,k;
- for(i=0;i<8;i++)
- {
- SCL=1;
- delay();
- k=(k<<1)|SDA;
- SCL=0;
- delay();
- }
- return k;
- }
- //----------
- void delay1(uchar x)
- {
- uchar a,b;
- for(a=x;a>0;a--)
- for(b=100;b>0;b--);
- }
- //----------
- void write_add(uchar address,uchar date) //写数据_调用层
- {
- start();
- write_byte(0xa0); //写器件地址
- respons(); //应答
- write_byte(address); //写器件内部存储地址
- respons();
- write_byte(date); //写入数据
- respons();
- stop(); //停止
- }
- //----------
- read_add(uchar address) //读数据_调用层
- {
- uchar date;
- start();
- write_byte(0xa0);
- respons();
- write_byte(address);
- respons();
- //------------------
- start();
- write_byte(0xa1);
- respons();
- date=read_byte();
- stop();
- return date;
- }
- //----------
- uchar I2C_data() //主函数初始化后读EEROM中的亮度值
- {
- uchar a;
- I2C_init();
- delay1(250);
- a=read_add(23);
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- return a;
- }
- //--------------------------------------------------------------------------/
- /*名称:系统程序设置
- 功能:PWM0设置,外部中断0设置,AD中断设置
- */
- void lcall_sezhi()
- {
- //-----------------------------------PWM设置
- CMOD=0x86; //------PCA模块PWM设置
- CCON=0x00; //CMOD=0X84为T0为信号源,这时将T0设置段落打开//0X80时则用12分频时钟信号
- CL=0x00; //CMOD=0X86使用外部脉冲信号,从P3.4脚加入信号
- CH=0x00;
- CCAPM1=0x42; //0X42=01000010B 允许比较器功能位P1.4脚输出PWM脉宽信号
- PCA_PWM1=0x00;//EPC1L和EPC1H在PWM模式下的值是0X00.
- CR=1; //启动计数器
- //====================================外部中断0设置
- EX0=1; //允许外部中断0
- IT0=1; //下降沿触发
- //====================================AD
- EADC_SPI=1; //允许ADC中断标志位
- AUXR|=0x10; //允许ADC中断
- P1M0=0x20;
- P1M1=0x00; //设置P1.2为AD输入
- ADC_CONTR=0xe2;
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- //-----------------------------------------------------------------------//
- EA=1; //开总中断
- }
- //===============================lcall_AD====================================//
- void lcall_AD(void)
- {
- ADC_CONTR=0xea; //启动AD转换
- }
- //---------------------------------------------------------------------------//
- /*名称:红外线解码数据计算处理
- 功能:开/并功能,键值档位计算,EEROM存储功能,给CCAP0H和CCAP0L送值
- */
- void IR_jiema_data(void)
- {
- if(qinlong==0x00) //0档位
- {//向CCAP0H,CCAP0L输入比较器的初值,以和CL CH计数器的值进行比较实现PWM调宽
- I2C_init();
- delay1(250);
- write_add(23,256-250);//写入EEROM地址23H,存储数据256-250
- CCAP0H=(256-250);
- CCAP0L=(256-250); //给PWM0传送脉宽值
- qinlong=0xff;
- }
- else if(qinlong==0x01) //1档位
- {
- I2C_init();
- delay1(250);
- write_add(23,256-240);
- CCAP0H=(256-240);
- CCAP0L=(256-240);
- qinlong=0xff;
- }
- else if(qinlong==0x02) //2档位
- {
- I2C_init();
- delay1(250);
- write_add(23,256-220);
- CCAP0H=(256-220);
- CCAP0L=(256-220);
- qinlong=0xff;
- }
- else if(qinlong==0x03) //3档位
- {
- I2C_init();
- delay1(250);
- write_add(23,256-200);
- CCAP0H=(256-200);
- CCAP0L=(256-200);
- qinlong=0xff;
- }
- else if(qinlong==0x04) //4档位
- {
- I2C_init();
- delay1(250);
- write_add(23,256-180);
- CCAP0H=(256-180);
- CCAP0L=(256-180);
- qinlong=0xff;
- }
- else if(qinlong==0x05) //5档位
- {
- I2C_init();
- delay1(250);
- write_add(23,256-160);
- CCAP0H=(256-160);
- CCAP0L=(256-160);
- qinlong=0xff;
- }
- else if(qinlong==0x06) //6档位
- {
- I2C_init();
- delay1(250);
- write_add(23,256-150);
- CCAP0H=(256-150);
- CCAP0L=(256-150);
- qinlong=0xff;
- }
- else if(qinlong==0x07) //7档位
- {
- I2C_init();
- delay1(250);
- write_add(23,256-100);
- CCAP0H=(256-100);
- CCAP0L=(256-100);
- qinlong=0xff;
- }
- else if(qinlong==0x08) //8档位
- {
- I2C_init();
- delay1(250);
- write_add(23,256-50);
- CCAP0H=(256-50);
- CCAP0L=(256-50);
- qinlong=0xff;
- }
- else if(qinlong==0x09) //9档位
- {
- I2C_init();
- delay1(250);
- write_add(23,256-10);
- CCAP0H=(256-10);
- CCAP0L=(256-10);
- qinlong=0xff;
- }
- }
- //---------------------------------------------------------------------------//
- /*名称:AD数码转换
- 功能:将电位器信号转换成8位数据,并用于EEROM存储和送入CCAP0H和CCAP0L中,从而
- 调节PWM0的输出
- */
- //---------------------------------------------------------------------------//
- void AD_jiema_data(void)
- { //AD转换后的数据处理
- if((AD_dat_over0<(AD_dat_over1+5))&&(AD_dat_over0>(AD_dat_over1-5)))
- { //如果在范围内(+5/-5)说明没调电位器,应使用存储值
- //给出+-5的范围是防止输入电压稍有变动,引起的判断错误
- I2C_init();
- delay1(250);
- CCAP0H=read_add(23);
- }
- else
- {
- CCAP0H=(256-AD_dat_over0); //有调动电位器,应使用电位器AD值
- I2C_init();
- delay1(250);
- write_add(23,AD_dat_over0); //刷新EEROM中的值
- }
- }
- //**********************************************************************************//
- /*名称:主函数
- 功能:完成系统的初始化和红外解码数据处理;AD转换数据处理;最终达到存储数据和调节PWM0.
- */
- //******************************主函数**********************************************//
- void main()
- {
- uchar a;
- lcall_sezhi(); //调用系统设置
- int_cushi(); //初始化系统检查
- lcall_AD(); //启动AD
- a=I2C_data(); //读I2C的数据
- while(1)
- {
- CCAP0H=(256-a);
- IR_jiema_data(); //红外解码数据处理
- AD_jiema_data(); //AD数据处理
- }
- }
- //***************************************************************************//
- /*名称:红外解码_外部中断0
- 功能:完成红外线的数据解码功能,解码后的数据处理由主程序中的子程序处理.
- */
- //---------------------------------------------------------------------------//
- void int0_hongwai() interrupt 0 using 0
- {
- uchar i,j,k,n;
- EX0=0;
- for(n=0;n<10;n++)
- {
- delay882();
- if(IR_RE==1)break;
- }
- while(IR_RE==0){};
- //------------------------
- //当遥控器持续按下则接收到一个9ms的低电平引导脉冲
- //以及一个2.2ms的高电平脉冲,和一个0.7ms的低电平脉冲,和一个96ms的高电平脉冲
- //以下是连续码的检测判断程序和4.5ms高电平判断
- //------------------------
- for(j=0;j<2;j++)
- {
- delay2400();
- if(IR_RE==0)break;
- }
- //-------------------------读取数字信号----------
- for(i=0;i<4;i++)
- {
- for(k=0;k<8;k++)
- {
- while(IR_RE==0){};
- delay882();
- if(IR_RE==0)
- {
- date[i]>>=1;
- date[i]=date[i]|0x00;
- }
- else if(IR_RE==1)
- {
- delay1000();
- date[i]>>=1;
- date[i]=date[i]|0x80;//0x80=10000000b
- }
- }
- }
- //-----------------------------------------------
- if(date[0]=~date[1]) //用户码和数据码判断
- {
- if(date[2]=~date[3])
- qinlong=date[2];
- }
- EX0=1;
- }
- //**********************************************************//
- /*名称:AD转换_AD中断程序
- 功能:完成AD转换数据传输,并同时清零AD中断标志位
- */
- //==========================================================//
- void AD_DAT12() interrupt 5 using 1
- {
- EADC_SPI=0; //允许ADC中断标志位
- j++;
- if(j==1)AD_dat_over0=ADC_DATA; //读数据
- else if(j==2)
- {
- AD_dat_over1=ADC_DATA; //
- j=0; //计数器归零
- }
- ADC_CONTR=0xea; //AD中断标志清零
- EADC_SPI=1;
- }
- //-----------------------END File---------------------------//
复制代码
|
|