|
本帖最后由 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---------------------------//
復制代碼
|
|