新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 基于MSP430的ADS7841驅動程序

        基于MSP430的ADS7841驅動程序

        作者: 時間:2016-11-13 來源:網絡 收藏
        師姐(博士)反向設計了ADS7841芯片。為了測試其穩定性和精度,所以幫忙寫了這個驅動程序。最初是師兄用FPGA寫的,但讀出來的數據差距太大,所以我就用430單片機幫忙搞了一個!但這個程序調試的并不順利,簡直就是痛苦,我昨天中午和晚上都沒吃飯!首先碰到I/O口壞的情況,還有就是這個芯片的 DATASHEET關于讀數的說明是錯的,害人不淺!據datasheet解釋是等待busy信號為低才開始讀數,其實這個時候已經晚了,會漏掉一位。所有上面這些問題我是借助邏輯分析儀看出來的,把抓出來的時序一點點的分析,終于發現了讀數方面DATASHEET的漏洞。還有就是她沒提寫數據和讀數據分別應該在時鐘的什么沿觸發。實在讓人郁悶~!~正常應該在下降沿寫指令,上升沿讀數據!
        折騰了一天才有結果,如果不是邏輯分析儀的幫忙,我估計死都不知道怎么死的。。
        好了,情況說明了,下面是代碼部分。
        *****************************************************************************
        ** 函數原型:unsigned int ADS7841_Read_Data(unsigned char Channel);
        ** 功 能:SPI總線的A/D ADS7841 驅動程序
        ** 入口參數:unsigned char Channel 表示選擇讀取通道
        ** 出口參數:unsigned int 返回所讀取得12位數據。
        ** 說 明:ADS7841為12位A/D,先對其進行設置:數據位D0---D7,其中D0---D1是
        ** 設置ADC的功耗模式,D2是模擬輸入通道設置,H為4個單通道,L為兩個
        ** 差分輸入,D3為mode,當mode(pin)接地時為12位采樣方式,接高電平時
        ** mode為1時8位采集,為0時12位采集,D4---D6為輸入通道選擇,D7為起始位
        ** 作  者: 沉思的魚
        ** 日  期: 2007年11月06日
        **-----------------------------------------------------------------------------
        ** 修 改 人:
        ** 日  期:
        *******************************************************************************/
        #include <msp430x14x.h>
        #define uint unsigned int
        #define uchar unsigned char
        #define ADS_S 0x80 //命令起始位
        #define ADS_MODE 0x08 //模式選擇。MODE端選擇直接接高電平,此位不用設置
        #define ADS_S_D 0x04 //輸入方式選擇
        #define ADS_POWER 0x00 //是否允許掉電
        #define DIR_CS P3DIR|=BIT0
        #define ADS_CS_1 P3OUT|=BIT0
        #define ADS_CS_0 P3OUT&=~BIT0 //片選
        #define ADS_DIR_IN P3DIR|=BIT1 //端口輸出模式
        #define ADS_DIN_1 P3OUT|=BIT1 //命令寫入AD
        #define ADS_DIN_0 P3OUT&=~BIT1
        #define ADS_DIR_OT P2DIR&=~BIT0 //端口為輸入模式
        #define ADS_CLK_DIR P4DIR|=BIT4 //端口為輸出模式
        #define ADS_CLK_1 P4OUT|=BIT4 //時鐘置1
        #define ADS_CLK_0 P4OUT&=~BIT4 //時鐘置0
        #define DIR_BUSY P4DIR&=~BIT0
        //#define DATA_IN ((P4IN>>2 & 0x01)
        #define DATA_IN (P2IN & 0x01)
        #define BUSY_IN (P4IN & 0x01) //讀輸入數據
        void Check_busy(void);
        void SPI_WR(uchar DATA);
        void Init_Port(void);
        void delay(uint temp);
        uint ADS7841_Read_Data(uchar Channel);
        uint temp_DATA[100];
        void delay(uint temp1)
        {
        int i;
        for(i=temp1;i>0;i--)
        {
        ;
        }
        }
        uint ADS7841_Read_Data(uchar Channel) //Channel=0:CH0;1:CH1;2:CH2;3:CH3;
        {
        uint ADCResult=0;
        uchar i,ADS_CHANNEL;
        uint TempBit =0;
        uchar COMMAND=0;
        switch (Channel)
        {
        case 0:ADS_CHANNEL=0x10;break; //通道選擇
        case 1:ADS_CHANNEL=0x50;break;
        case 2:ADS_CHANNEL=0x20;break;
        case 3:ADS_CHANNEL=0x60;break;
        default:ADS_CHANNEL=0x10;break;
        }
        COMMAND=(ADS_S|ADS_CHANNEL|ADS_S_D|ADS_POWER);
        ADS_CLK_0;
        ADS_DIN_0; ///DIN先置0
        ADS_CS_0; //;片選信號
        //SPI_WR(COMMAND); //SPI總線寫命令子程序
        //ADS_DIR_IN; //端口定義為輸出模式,上升沿發送,下降沿接受
        for(i=0;i<8;i++)
        {
        ADS_CLK_1;
        if( (COMMAND & 0x80) ==0x80)
        {
        ADS_DIN_1; //寫入指令
        }
        else
        {
        ADS_DIN_0;
        }
        COMMAND<<=1; //左移
        delay(5);
        ADS_CLK_0;
        delay(5); //模擬SPI串行接口 發送數據
        }
        delay(5);
        ADS_CLK_0;
        Check_busy();
        //delay(5);
        for(i=0;i<12;i++)
        { //上升沿讀出數據
        ADS_CLK_0;
        delay(4);
        if( DATA_IN==0x01 )
        {
        TempBit=1;
        }
        else
        {
        TempBit=0;
        }
        ADS_CLK_1;
        ADCResult=((ADCResult<<1)|TempBit); //模擬SPI串行接口,接收數據
        delay(5);
        }
        ADS_CLK_0;
        for(i=0;i<4;i++)
        {
        ADS_CLK_1;
        delay(5);
        ADS_CLK_0;
        delay(5);
        }
        ADS_CS_1; //屏蔽片選
        return ADCResult;
        }
        void Check_busy(void)
        {
        int temp;
        //DIR_BUSY; //端口設置為輸入方式
        ADS_CLK_1;
        temp=BUSY_IN;
        ADS_CLK_0;
        while( (temp&0x01)==0) //檢測到高電平就開始讀數。。不然會丟一位
        {
        ADS_CLK_1; //讀端口狀態....
        temp=BUSY_IN;
        //delay(5); //
        ADS_CLK_0;
        }
        //
        /* do
        {
        ADS_CLK_0; //讀端口狀態....
        temp=BUSY_IN;
        delay(5); //
        ADS_CLK_1;
        }while((temp&0x01)!=0); //高位為1為忙信號*/
        }
        void SPI_WR(uchar DATA)
        {
        uint i;
        ADS_DIR_IN; //端口定義為輸出模式,上升沿發送,下降沿接受
        for(i=0;i<8;i++)
        {
        ADS_CLK_1;
        if( (DATA & 0x80) ==0x80)
        {
        ADS_DIN_1; //寫入指令
        }
        else
        {
        ADS_DIN_0;
        }
        DATA<<=1; //左移
        ADS_CLK_0;
        delay(5); //模擬SPI串行接口 發送數據
        }
        delay(5);
        ADS_CLK_0;
        }
        void Init_Port(void)
        {
        P3SEL=0X00;
        P4SEL=0X00;
        ADS_DIR_IN;
        ADS_DIR_OT;
        ADS_CLK_DIR;
        DIR_BUSY;
        DIR_CS;
        ADS_CLK_0;
        //delay(5);
        ADS_CS_1;
        // ADS_CLK_1;
        }
        void main(void)
        {
        WDTCTL = WDTPW+WDTHOLD; //關看門狗
        Init_Port(); //端口初始化
        uint flag=0;
        uint i;
        while(1)
        {
        for(i=0;i<5;i++)
        {
        temp_DATA[i]=ADS7841_Read_Data(0);
        delay(10);
        }
        flag=1;
        }

        }


        評論


        技術專區

        關閉
        主站蜘蛛池模板: 张家口市| 酉阳| 沿河| 肇源县| 天长市| 灵石县| 建始县| 阿拉善右旗| 龙海市| 连云港市| 信丰县| 郸城县| 布拖县| 松潘县| 上林县| 松滋市| 宁陵县| 汪清县| 新晃| 凭祥市| 柘城县| 翼城县| 措勤县| 阜南县| 略阳县| 湘潭市| 唐海县| 鲁山县| 冀州市| 兖州市| 庆安县| 乡城县| 奎屯市| 图们市| 那曲县| 汉中市| 西盟| 永清县| 营口市| 阿拉善左旗| 宁远县|