新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > ADDA系列PCF8591的驅動程序

        ADDA系列PCF8591的驅動程序

        作者: 時間:2016-11-18 來源:網絡 收藏
        /*************************此部分為I2C總線驅動程序*************************************/

        #include
        #include
        #include

        本文引用地址:http://www.104case.com/article/201611/315912.htm

        #define NOP() _nop_() /* 定義空指令 */
        #define _Nop() _nop_() /*定義空指令*/


        sbit SCL=P2^0; //I2C 時鐘
        sbit SDA=P2^1; //I2C 數據
        bit ack; /*應答標志位*/

        /*******************************************************************
        起動總線函數
        函數原型: void Start_I2c();
        功能: 啟動I2C總線,即發送I2C起始條件.
        ********************************************************************/
        void Start_I2c()
        {
        SDA=1; /*發送起始條件的數據信號*/
        _Nop();
        SCL=1;
        _Nop(); /*起始條件建立時間大于4.7us,延時*/
        _Nop();
        _Nop();
        _Nop();
        _Nop();
        SDA=0; /*發送起始信號*/
        _Nop(); /* 起始條件鎖定時間大于4μs*/
        _Nop();
        _Nop();
        _Nop();
        _Nop();
        SCL=0; /*鉗住I2C總線,準備發送或接收數據 */
        _Nop();
        _Nop();
        }

        /*******************************************************************
        結束總線函數
        函數原型: void Stop_I2c();
        功能: 結束I2C總線,即發送I2C結束條件.
        ********************************************************************/
        void Stop_I2c()
        {
        SDA=0; /*發送結束條件的數據信號*/
        _Nop(); /*發送結束條件的時鐘信號*/
        SCL=1; /*結束條件建立時間大于4μs*/
        _Nop();
        _Nop();
        _Nop();
        _Nop();
        _Nop();
        SDA=1; /*發送I2C總線結束信號*/
        _Nop();
        _Nop();
        _Nop();
        _Nop();
        }

        /*******************************************************************
        字節數據發送函數
        函數原型: void SendByte(UCHAR c);
        功能: 將數據c發送出去,可以是地址,也可以是數據,發完后等待應答,并對
        此狀態位進行操作.(不應答或非應答都使ack=0)
        發送數據正常,ack=1; ack=0表示被控器無應答或損壞。
        ********************************************************************/
        void SendByte(unsigned char c)
        {
        unsigned char BitCnt;

        for(BitCnt=0;BitCnt<8;BitCnt++) /*要傳送的數據長度為8位*/
        {
        if((c< else SDA=0;
        _Nop();
        SCL=1; /*置時鐘線為高,通知被控器開始接收數據位*/
        _Nop();
        _Nop(); /*保證時鐘高電平周期大于4μs*/
        _Nop();
        _Nop();
        _Nop();
        SCL=0;
        }

        _Nop();
        _Nop();
        SDA=1; /*8位發送完后釋放數據線,準備接收應答位*/
        _Nop();
        _Nop();
        SCL=1;
        _Nop();
        _Nop();
        _Nop();
        if(SDA==1)ack=0;
        else ack=1; /*判斷是否接收到應答信號*/
        SCL=0;
        _Nop();
        _Nop();
        }

        /*******************************************************************
        字節數據接收函數
        函數原型: UCHAR RcvByte();
        功能: 用來接收從器件傳來的數據,并判斷總線錯誤(不發應答信號),
        發完后請用應答函數應答從機。
        ********************************************************************/
        unsigned char RcvByte()
        {
        unsigned char retc;
        unsigned char BitCnt;

        retc=0;
        SDA=1; /*置數據線為輸入方式*/
        for(BitCnt=0;BitCnt<8;BitCnt++)
        {
        _Nop();
        SCL=0; /*置時鐘線為低,準備接收數據位*/
        _Nop();
        _Nop(); /*時鐘低電平周期大于4.7μs*/
        _Nop();
        _Nop();
        _Nop();
        SCL=1; /*置時鐘線為高使數據線上數據有效*/
        _Nop();
        _Nop();
        retc=retc<<1;
        if(SDA==1)retc=retc+1; /*讀數據位,接收的數據位放入retc中 */
        _Nop();
        _Nop();
        }
        SCL=0;
        _Nop();
        _Nop();
        return(retc);
        }

        /********************************************************************
        應答子函數
        函數原型: void Ack_I2c(bit a);
        功能: 主控器進行應答信號(可以是應答或非應答信號,由位參數a決定)
        ********************************************************************/
        void Ack_I2c(bit a)
        {

        if(a==0)SDA=0; /*在此發出應答或非應答信號 */
        else SDA=1;
        _Nop();
        _Nop();
        _Nop();
        SCL=1;
        _Nop();
        _Nop(); /*時鐘低電平周期大于4μs*/
        _Nop();
        _Nop();
        _Nop();
        SCL=0; /*清時鐘線,鉗住I2C總線以便繼續接收*/
        _Nop();
        _Nop();
        }

        #include
        #include

        #define PCF8591 0x90 //PCF8591 地址


        //else IO
        sbit LS138A=P2^2;
        sbit LS138B=P2^3;
        sbit LS138C=P2^4;

        //此表為 LED 的字模, 共陰數碼管 0-9 -
        unsigned char code Disp_Tab[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

        unsigned char AD_CHANNEL;
        unsigned long xdata LedOut[8];
        unsigned int D[32];

        /*******************************************************************
        DAC 變換, 轉化函數
        *******************************************************************/
        bit DACconversion(unsigned char sla,unsigned char c, unsigned char Val)
        {
        Start_I2c(); //啟動總線
        SendByte(sla); //發送器件地址
        if(ack==0)return(0);
        SendByte(c); //發送控制字節
        if(ack==0)return(0);
        SendByte(Val); //發送DAC的數值
        if(ack==0)return(0);
        Stop_I2c(); //結束總線
        return(1);
        }

        /*******************************************************************
        ADC發送字節[命令]數據函數
        *******************************************************************/
        bit ISendByte(unsigned char sla,unsigned char c)
        {
        Start_I2c(); //啟動總線
        SendByte(sla); //發送器件地址
        if(ack==0)return(0);
        SendByte(c); //發送數據
        if(ack==0)return(0);
        Stop_I2c(); //結束總線
        return(1);
        }

        /*******************************************************************
        ADC讀字節數據函數
        *******************************************************************/
        unsigned char IRcvByte(unsigned char sla)
        { unsigned char c;

        Start_I2c(); //啟動總線
        SendByte(sla+1); //發送器件地址,地址加一的原因是地址字的最后一位0為寫,1為讀
        if(ack==0)return(0);
        c=RcvByte(); //讀取數據0

        Ack_I2c(1); //發送非就答位
        Stop_I2c(); //結束總線
        return(c);
        }

        //******************************************************************/
        main()
        { char i,j;

        while(1)
        {/********以下AD-DA處理*************/
        switch(AD_CHANNEL)
        {
        case 0: ISendByte(PCF8591,0x41);
        D[0]=IRcvByte(PCF8591)*2; //ADC0 模數轉換1,乘以2的原因是把結果00~0xff換算成0~510,除以100就是實際采樣值了
        break;

        case 1: ISendByte(PCF8591,0x42);
        D[1]=IRcvByte(PCF8591)*2; //ADC1 模數轉換2
        break;

        case 2: ISendByte(PCF8591,0x43);
        D[2]=IRcvByte(PCF8591)*2; //ADC2模數轉換3
        break;

        case 3: ISendByte(PCF8591,0x40);
        D[3]=IRcvByte(PCF8591)*2; //ADC3 模數轉換4
        break;

        case 4: DACconversion(PCF8591,0x40, D[4]/4); //DAC 數模轉換
        break;
        }

        // D[4]=400; //數字--->>模擬輸出
        D[4]=D[3];
        if(++AD_CHANNEL>4) AD_CHANNEL=0;

        /********以下將AD的值送到LED數碼管顯示*************/

        LedOut[0]=Disp_Tab[D[1]%10000/1000];
        LedOut[1]=Disp_Tab[D[1]%1000/100];
        LedOut[2]=Disp_Tab[D[1]%100/10]|0x80;
        LedOut[3]=Disp_Tab[D[1]%10];

        LedOut[4]=Disp_Tab[D[0]%10000/1000];
        LedOut[5]=Disp_Tab[D[0]%1000/100];
        LedOut[6]=Disp_Tab[D[0]%100/10]|0x80;
        LedOut[7]=Disp_Tab[D[0]%10];


        for( i=0; i<8; i++)
        { P1 = LedOut[i];

        switch(i) //使用switch 語句控制138譯碼器 也可以是用查表的方式 學員可以試著自己修改
        {
        case 0:LS138A=0; LS138B=0; LS138C=0; break;
        case 1:LS138A=1; LS138B=0; LS138C=0; break;
        case 2:LS138A=0; LS138B=1; LS138C=0; break;
        case 3:LS138A=1; LS138B=1; LS138C=0; break;
        case 4:LS138A=0; LS138B=0; LS138C=1; break;
        case 5:LS138A=1; LS138B=0; LS138C=1; break;
        case 6:LS138A=0; LS138B=1; LS138C=1; break;
        case 7:LS138A=1; LS138B=1; LS138C=1; break;

        }

        for (j = 0 ; j<90 ;j++) { ;} //掃描間隔時間
        }

        P1 = 0;

        }
        }



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 德阳市| 兴义市| 怀化市| 吴堡县| 射阳县| 曲周县| 耒阳市| 晋宁县| 于都县| 昌乐县| 开江县| 凤庆县| 阿勒泰市| 历史| 闻喜县| 扬州市| 时尚| 南华县| 六枝特区| 大城县| 丰台区| 桐乡市| 崇文区| 马山县| 扎赉特旗| 栾川县| 五台县| 江达县| 东辽县| 桐梓县| 慈溪市| 高州市| 耿马| 福清市| 茶陵县| 申扎县| 康马县| 青海省| 色达县| 五华县| 大埔县|