【STM32H7教程】第93章 STM32H7的SPI總線應用之驅動ADS1256(8通道24bit ADC, 增益可編程)

完整教程下載地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980

第93章       STM32H7的SPI總線應用之驅動ADS1256(8通道24bit ADC, 增益可編程)

本章節爲大家講解8通道24bit ADC芯片驅動實現。

93.1 初學者重要提示

93.2 ADC結構分類

93.3 ADS1256硬件設計

93.4 ADS1256關鍵知識點整理(重要)

93.5 ADS1256驅動設計

93.6 ADS1256板級支持包(bsp_spi_ads1256)

93.7 ADS1256實際測試效果(10uV抖動)

93.8 ADS1256驅動移植和使用

93.9 實驗例程設計框架

93.10 實驗例程說明(MDK)

93.11 實驗例程說明(IAR)

93.12 總結

 

 

93.1 初學者重要提示

  1.   ADS1256的模擬部分供電5V,SPI數字接口電平3.3V。
  2.   ADS1256的PGA可以編程增益支持: 1、2、4、8、16、32、64。
  3.   ADS1256支持自動校準 (當設置了PGA,BUF使能、數據採樣率時,會啓動自校準)。
  4.   ADS1256支持8通道單端ADC採集或者4通道差分採集。
  5.   ADS1256支持正負5V差分採集,但不支持負壓,使用時要注意。
  6.   ADS1256時序操作稍有點特殊,所以本章是採用的模擬SPI控制。
  7.   ADS1256數據手冊,模塊原理圖(通用版)和接線圖都已經放到本章教程配置例子的Doc文件裏。
  8.   ADC 的專業術語詮釋文檔,推薦大家看看:http://www.armbbs.cn/forum.php?mod=viewthread&tid=89414
  9.   測試時,務必使用外置電源爲開發板供電,因爲ADS1256需要5V供電電壓。板子上插入ADS1256模塊時,注意對齊。

93.2 ADC結構分類

這裏將六種DAC結構爲大家做個普及。注,這些知識翻譯自美信和TI的英文技術手冊。

 

 

93.2.1 SAR ADC(逐次逼近型)

逐次逼近型ADC通常是中高分辨率的首選架構,採樣速率通常低於5Msps。SAR ADC最常見的分辨率範圍是8位到20位,並具有低功耗和小尺寸的特點。這種組合使其非常適合各種應用,例如自動測試設備,電池供電的設備,數據採集系統,醫療儀器,電機和過程控制,工業自動化,電信,測試和測量,便攜式系統,高速閉環系統和窄帶接收器。

93.2.2 Sigma-Delta ADC

Sigma-delta ADC主要用於低速應用中,該應用需要通過過採樣來權衡速度和分辨率,然後進行濾波以降低噪聲。24位sigma-delta轉換器用於自動化測試設備,高精度便攜式傳感器,醫療和科學儀器以及地震數據採集等應用中。

93.2.3 Integrating ADC

集成ADC提供高分辨率,並且可以提供良好的線路頻率和噪聲抑制。集成架構提供了一種新穎且直接的方法,可將低帶寬模擬信號轉換爲數字表示形式。這些類型的轉換器通常包括用於LCD或LED顯示器的內置驅動器,並且在許多便攜式儀器應用中都可以找到,包括數字面板表和數字萬用表。

93.2.4 FLASH ADC

Flash ADC是將模擬信號轉換爲數字信號的最快方法。它們適用於需要非常大帶寬的應用。然而,閃存轉換器功率高,具有相對較低的分辨率,並且可能非常昂貴。這將它們限制在通常無法以其他任何方式解決的高頻應用中。示例包括數據採集,衛星通信,雷達處理,示波器和高密度磁盤驅動器。

93.2.5 Pipelined ADC

流水線ADC已成爲最受歡迎的ADC體系結構,其採樣率從每秒幾兆採樣(MS / s)到最高100MS / s +,分辨率爲8至16位。它們提供的分辨率和採樣率,可覆蓋各種應用,包括CCD成像,超聲醫學成像,數字接收器,基站,數字視頻(例如HDTV),xDSL,電纜調制解調器和快速以太網。

93.2.6 Two Step ADC

兩步ADC也稱爲子範圍轉換器,有時也稱爲多步或half flash(比Flash架構慢)。這是Flash ADC和流水線ADC的交叉點。與Flash ADC相比,可以實現更高的分辨率或更小的裸片尺寸。

93.3 ADS1256硬件設計

這裏將開發板上的ADS1256硬件接口,ADS1256模塊爲大家做個說明。

ADS1256的原理圖論壇下載:

http://www.armbbs.cn/forum.php?mod=viewthread&tid=97547

93.3.1 ADS1256硬件接口

V7板子上ADS1256模塊的插座的原理圖如下:

 

實際對應開發板的位置如下:

 

爲了方便大家更好的理解接線,下面是框圖:

 

93.3.2 ADS1256模塊

產品規格:

1、 單電源5.0V DC供電,提供正負5V信號採樣功能。

2、 MCU接口:SPI。

3、 主ADC芯片:ADS1256  (全新進口原裝正品)。

4、 電壓基準,之前採用的LM285-2.5,現在採用的REF5025(全新進口原裝正品)。

5、 輸入電路帶分壓電阻和R-C濾波,方便客戶自己變更增益範圍。

6、 芯片內帶可編程增益放大器,增益範圍:1-64倍。

7、 芯片內部輸入帶緩衝放大器,可以直接連接傳感器。

正面:

 

 

反面:

 

 

接線圖:

 

 

93.4 ADS1256關鍵知識點整理(重要)

驅動ADS1256需要對下面這些知識點有個認識。

93.4.1 ADS1256基礎信息

ADS1256是TI公司推出的微功耗、高精度、8通道、 24位△-∑型高性能模數轉換器(ADC)。該器件提供高達23比特的無噪聲精度、數據速率高達30kSPS(次採樣/秒)、0.0010%非線性特性(最大值)以及衆多的板上外設(輸入模擬多路開關、輸入緩衝器、可編程增益放大器和可編程數字濾波器等),可爲設計人員帶來完整而高分辨率的量測解決方案。

  •   24位無數據丟失;
  •   高達23比特的無噪聲精度;
  •   低非線性度: ±0.0010% ;
  •   數據採樣率可達30kSPS ;
  •   採用單週期轉換模式;
  •   帶有模擬多路開關,具有傳感器接口(可配置爲4路差動輸入或8路單極輸入) ;
  •   帶有輸入緩衝器( BUF) ;
  •   帶有串行外設接口( SPI) ;
  •   內含低噪聲可編程增益放大器( PGA ) ,所有的PGA均具有自校準和系統校準;
    •  PGA= 1時,可提供高達25.3位的有效分辨率;
    •  PGA = 64時,可提供高達22.5位的有效分辨率;
  •   模擬輸入電壓爲5V ,數字電壓爲1.8~3.6V ;
  •   正常模式下功耗低至38mW ,備用模式下功耗爲0.4mW。

93.4.2 ADS1256常用引腳的作用

ADS1256的封裝形式:

 

 

這裏把常用的幾個引腳做個說明:

  •   AVDD

模擬電源供電。

  •   AGND

模擬地。

  •   VREFN

負參考電壓輸入。

  •   VREFP

正參考電壓輸入。

  •   AINCOM

模擬公共輸入。

  •   AIN0 – AIN7

模擬輸入通道0到通道7

  •   SYNC/PDWN

同步,掉電輸入。

  •   RESET

復位引腳。

  •   DVDD

數字電源。

  •   DGND

數字地。

  •   XTAL1,XTAL2

晶振輸入端。

  •   CS

片選輸入端。

  •   DRDY

數據就緒輸出信號引腳。

  •   DOUT

數據輸出。

  •   DIN

數據輸入。

  •   SCLK

時鐘引腳。

  •   D0,D1,D2,D3

通用GPIO

93.4.3 ADS1256輸出電壓計算公式

ADS1256的計算公式如下:

 

 

最小單位值是2 * VREF/(PGA * (2^23 − 1))

採用二進制補碼錶示(其實就是24bit有符號數,我們將轉換結果定義爲int32_t即可)。

93.4.4 ADS1256時序圖

驅動ADS1256主要是兩個時序圖需要了解,讀寫時序:

 

 

  •   t1:SPI時鐘週期:

外部晶振頻率 = 7.68MHz,

              時鐘頻率 tCLK = 1/7.68M = 0.13uS

              輸出數據週期 tDATA =  1 / 30K = 0.033mS  (按30Ksps計算)

       對SPI的時鐘速度要求:

              最快 4個tCLK = 0.52uS

              最慢 10個tDATA = 0.3mS (按 30Ksps 計算)

 

 

 

  •   t2H,t2L :脈衝高低電平:

SCL高電平和低電平持續時間最小 200ns。

 

 

數據讀取流程:

 

 

  •   第1步:ADS1256_SetChannal(g_tADS1256.Channel)切換模擬通道。
  •   第2步:發送SYNC同步命令。
  •   第3步:喚醒。
  •   第4步:讀取數據。

這個過程中特別注意讀取的是上次轉換的數據。

93.4.5 ADS1256的增益和測量範圍問題

ADS1256的增益和測量範圍關係如下:

 

 

比如增益是1時,測量範圍是正負5V,增益是64時,測量範圍是正負78.125mV。

93.4.6 ADS1256輸入緩衝器

開關輸入緩衝器時,影響到的幾個參數,大家需要做個瞭解。

開緩衝的情況下,輸入參考值噪聲。

 

 

關閉緩衝時的輸入參考噪聲:

 

 

開緩衝的情況下,有效分辨率:

 

 

關閉緩衝時的有效位數:

 

 

打開緩衝器後的輸入阻抗:

 

 

 

關閉緩衝器後的輸入阻抗:

 

 

 

93.4.7 ADS1256支持的採樣率

ADS1256支持的採樣率如下,這裏特別注意,因爲切換通道和讀數據耗時 123微秒, 因此掃描中斷模式工作時,最大速率 = DRATE_1000SPS。

 

 

93.4.8 ADS1256的多路選擇器,單端和多端輸入

ADS1256的8路支持是通過多路選擇器實現,8路採樣時是選擇相應通道進行採樣:

 

 

實際應用的的8路單端採樣和4路差分採樣效果如下:

 

 

93.5 ADS1256驅動設計

ADS1256的程序驅動框架設計如下:

 

有了這個框圖,程序設計就比較好理解了。

93.5.1 第1步,ADS1256所涉及到的GPIO配置

這裏需要把用到的GPIO時鐘、GPIO引腳配置好:

/*
    ADS1256模塊    STM32-V7開發板(示波器接口)
      +5V   <------  5.0V      5V供電
      GND   -------  GND       地
      DRDY  ------>  PC6       準備就緒
      CS    <------  PC7       SPI_CS
      DIN   <------  PG10      SPI_MOSI
      DOUT  ------>  PA5       SPI_MISO
      SCLK  <------  PA4       SPI時鐘
      GND   -------  GND       地
      PDWN  <------  PB7       掉電控制
      RST   <------  PC3       復位信號
      NC   空腳
      NC   空腳
*/

#ifdef SOFT_SPI        /* 軟件SPI */
    /* 定義GPIO端口 */    
    #define SCK_CLK_ENABLE()     __HAL_RCC_GPIOA_CLK_ENABLE()
    #define SCK_GPIO            GPIOA
    #define SCK_PIN            GPIO_PIN_4
    #define SCK_1()            SCK_GPIO->BSRR = SCK_PIN
    #define SCK_0()            SCK_GPIO->BSRR = ((uint32_t)SCK_PIN << 16U)    

    #define DIN_CLK_ENABLE()     __HAL_RCC_GPIOG_CLK_ENABLE()
    #define DIN_GPIO            GPIOG
    #define DIN_PIN            GPIO_PIN_10
    #define DIN_1()            DIN_GPIO->BSRR = DIN_PIN
    #define DIN_0()            DIN_GPIO->BSRR = ((uint32_t)DIN_PIN << 16U)    

    #define CS_CLK_ENABLE()     __HAL_RCC_GPIOC_CLK_ENABLE()
    #define CS_GPIO            GPIOC
    #define CS_PIN            GPIO_PIN_7
    #define CS_1()            CS_GPIO->BSRR = CS_PIN
    #define CS_0()            CS_GPIO->BSRR = ((uint32_t)CS_PIN << 16U)    

    #define DOUT_CLK_ENABLE()     __HAL_RCC_GPIOA_CLK_ENABLE()
    #define DOUT_GPIO            GPIOA
    #define DOUT_PIN            GPIO_PIN_5
    #define DOUT_IS_HIGH()        ((DOUT_GPIO->IDR & DOUT_PIN) != 0)

    #define DRDY_CLK_ENABLE()     __HAL_RCC_GPIOC_CLK_ENABLE()
    #define DRDY_GPIO            GPIOC
    #define DRDY_PIN            GPIO_PIN_6
    #define DRDY_IS_LOW()        ((DRDY_GPIO->IDR & DRDY_PIN) == 0)
    #define DRDY_IRQn             EXTI9_5_IRQn
    #define DRDY_IRQHandler        EXTI9_5_IRQHandler    

    /* PDWN  <------  PB7       掉電控制 */
    #define PWDN_CLK_ENABLE()     __HAL_RCC_GPIOB_CLK_ENABLE()
    #define PWDN_GPIO            GPIOB
    #define PWDN_PIN            GPIO_PIN_7
    #define PWDN_1()            PWDN_GPIO->BSRR = PWDN_PIN
    #define PWDN_0()            PWDN_GPIO->BSRR = ((uint32_t)PWDN_PIN << 16U)            
    
    /*  RST   <------  PC3       復位信號     */
    #define RST_CLK_ENABLE()     __HAL_RCC_GPIOC_CLK_ENABLE()
    #define RST_GPIO            GPIOC
    #define RST_PIN            GPIO_PIN_3
    #define RST_1()            RST_GPIO->BSRR = RST_PIN
    #define RST_0()            RST_GPIO->BSRR = ((uint32_t)RST_PIN << 16U)            
#endif

/*
*********************************************************************************************************
*    函 數 名: bsp_InitADS1256
*    功能說明: 配置STM32的GPIO和SPI接口,用於連接 ADS1256
*    形    參: 無
*    返 回 值: 無
*********************************************************************************************************
*/
void bsp_InitADS1256(void)
{
#ifdef SOFT_SPI
    GPIO_InitTypeDef gpio_init;
    
    RST_1();
    PWDN_1();
    CS_1();
    SCK_0();        /* SPI總線空閒時,鍾線是低電平 */
    DIN_1();

    /* 打開GPIO時鐘 */
    SCK_CLK_ENABLE();
    DIN_CLK_ENABLE();
    CS_CLK_ENABLE();
    DOUT_CLK_ENABLE();
    DRDY_CLK_ENABLE();
    PWDN_CLK_ENABLE();
    RST_CLK_ENABLE();

    /* 配置幾個推完輸出IO */
    gpio_init.Mode = GPIO_MODE_OUTPUT_PP;        /* 設置推輓輸出 */
    gpio_init.Pull = GPIO_NOPULL;                /* 上下拉電阻不使能 */
    gpio_init.Speed = GPIO_SPEED_FREQ_HIGH;      /* GPIO速度等級 */        
    
    gpio_init.Pin = SCK_PIN;    
    HAL_GPIO_Init(SCK_GPIO, &gpio_init);    

    gpio_init.Pin = DIN_PIN;    
    HAL_GPIO_Init(DIN_GPIO, &gpio_init);    
    
    gpio_init.Pin = CS_PIN;    
    HAL_GPIO_Init(CS_GPIO, &gpio_init);    

    gpio_init.Pin = PWDN_PIN;    
    HAL_GPIO_Init(PWDN_GPIO, &gpio_init);    

    /* DRDY 設置爲輸入 */
    gpio_init.Mode = GPIO_MODE_INPUT;        /* 設置輸入 */
    gpio_init.Pull = GPIO_NOPULL;            /* 上下拉電阻不使能 */
    gpio_init.Speed = GPIO_SPEED_FREQ_HIGH;      /* GPIO速度等級 */
    
    gpio_init.Pin = DRDY_PIN;    
    HAL_GPIO_Init(DRDY_GPIO, &gpio_init);    

    gpio_init.Pin = DOUT_PIN;    
    HAL_GPIO_Init(DOUT_GPIO, &gpio_init);    
#endif
}

這裏重點注意DRDY轉換就緒引腳的配置,DRDY_IRQn和DRDY_IRQHandler不要配置錯了。

93.5.2 第2步,ADS1256的8bit讀寫函數實現

讀寫函數實現如下:

/*
*********************************************************************************************************
*    函 數 名: ADS1256_Send8Bit
*    功能說明: 向SPI總線發送8個bit數據。 不帶CS控制。
*    形    參: _data : 數據
*    返 回 值: 無
*********************************************************************************************************
*/
static void ADS1256_Send8Bit(uint8_t _data)
{
    uint8_t i;

    /* 連續發送多個字節時,需要延遲一下 */
    ADS1256_DelaySCLK();
    ADS1256_DelaySCLK();

    /* ADS1256 要求 SCL高電平和低電平持續時間最小 200ns  */
    for(i = 0; i < 8; i++)
    {
        if (_data & 0x80)
        {
            DIN_1();
        }
        else
        {
            DIN_0();
        }
        SCK_1();                
        ADS1256_DelaySCLK();        
        _data <<= 1;        
        SCK_0();            /* <----  ADS1256 是在SCK下降沿採樣DIN數據, 數據必須維持 50nS */
        ADS1256_DelaySCLK();        
    }
}

/*
*********************************************************************************************************
*    函 數 名: ADS1256_Recive8Bit
*    功能說明: 從SPI總線接收8個bit數據。 不帶CS控制。
*    形    參: 無
*    返 回 值: 無
*********************************************************************************************************
*/
static uint8_t ADS1256_Recive8Bit(void)
{
    uint8_t i;
    uint8_t read = 0;

    ADS1256_DelaySCLK();
    /* ADS1256 要求 SCL高電平和低電平持續時間最小 200ns  */
    for (i = 0; i < 8; i++)
    {
        SCK_1();
        ADS1256_DelaySCLK();
        read = read<<1;
        SCK_0();
        if (DOUT_IS_HIGH())
        {
            read++;
        }        
        ADS1256_DelaySCLK();
    }
    return read;
}

讀寫的實現完全按照下面的時序實現:

 

 

這裏主要注意時間實現:

t1:SPI時鐘週期:

外部晶振頻率 = 7.68MHz,

              時鐘頻率 tCLK = 1/7.68M = 0.13uS

              輸出數據週期 tDATA =  1 / 30K = 0.033mS  (按30Ksps計算)

       對SPI的時鐘速度要求:

              最快 4個tCLK = 0.52uS

              最慢 10個tDATA = 0.3mS (按 30Ksps 計算)

 

 

t2H,t2L :脈衝高低電平:

SCL高電平和低電平持續時間最小 200ns。

 

 

93.5.3 第3步,ADS1256的24bit ADC數據讀取

實現代碼如下:

/*
*********************************************************************************************************
*    函 數 名: ADS1256_ReadData
*    功能說明: 讀ADC數據
*    形    參: 無
*    返 回 值: 無
*********************************************************************************************************
*/
static int32_t ADS1256_ReadData(void)
{
    uint32_t read = 0;

    CS_0();    /* SPI片選 = 0 */

    ADS1256_Send8Bit(CMD_RDATA);    /* 讀數據的命令 */
    
    ADS1256_DelayDATA();    /* 必須延遲才能讀取芯片返回數據 */

    /* 讀採樣結果,3個字節,高字節在前 */
    read = ADS1256_Recive8Bit() << 16;
    read += ADS1256_Recive8Bit() << 8;
    read += ADS1256_Recive8Bit() << 0;

    CS_1();    /* SPI片選 = 1 */
    
    /* 負數進行擴展。24位有符號數擴展爲32位有符號數 */
    if (read & 0x800000)
    {
        read += 0xFF000000;
    }
    
    return (int32_t)read;
}

這段代碼裏面關鍵是24bit數據的補碼處理。對負數進行擴展,24位有符號數擴展爲32位有符號數。

93.5.4 第3步,ADS1256增益和採樣率配置

代碼如下:

/*
*********************************************************************************************************
*    函 數 名: ADS1256_CfgADC
*    功能說明: 配置ADC參數,增益和數據輸出速率
*    形    參: _gain : 支持增益參數。
*                    ADS1256_GAIN_1
*                    ADS1256_GAIN_2    
*                    ADS1256_GAIN_4
*                    ADS1256_GAIN_8
*                    ADS1256_GAIN_16
*                    ADS1256_GAIN_32
*                    ADS1256_GAIN_64
*
*             _drate : 數據輸出速率,不推薦超過1000SPS
*                    ADS1256_30000SPS
*                    ADS1256_15000SPS
*                    ADS1256_7500SPS
*                    ADS1256_3750SPS
*                    ADS1256_2000SPS
*                    ADS1256_1000SPS
*                    ADS1256_500SPS
*                    ADS1256_100SPS
*                    ADS1256_60SPS
*                    ADS1256_50SPS
*                    ADS1256_30SPS
*                    ADS1256_25SPS
*                    ADS1256_15SPS
*                    ADS1256_10SPS
*                    ADS1256_5SPS
*                    ADS1256_2d5SPS
*    返 回 值: 無
*********************************************************************************************************
*/
void ADS1256_CfgADC(ADS1256_GAIN_E _gain, ADS1256_DRATE_E _drate)
{    
    g_tADS1256.Gain = _gain;
    g_tADS1256.DataRate = _drate;
    
    ADS1256_StopScan();            /* 暫停CPU中斷 */
    
    ADS1256_ResetHard();        /* 硬件復位 */

    ADS1256_WaitDRDY();

    {
        uint8_t buf[4];        /* 暫存ADS1256 寄存器配置參數,之後連續寫4個寄存器 */
    
        buf[0] = (0 << 3) | (1 << 2) | (1 << 1);
        
        buf[1] = 0x08;    /* 高四位0表示AINP接 AIN0,  低四位8表示 AINN 固定接 AINCOM */

        buf[2] = (0 << 5) | (0 << 2) | (_gain << 1);

        /* 因爲切換通道和讀數據耗時 123uS, 因此掃描中斷模式工作時,最大速率 = DRATE_1000SPS */
        buf[3] = s_tabDataRate[_drate];    // DRATE_10SPS;    /* 選擇數據輸出速率 */
        
        CS_0();    /* SPI片選 = 0 */
        ADS1256_Send8Bit(CMD_WREG | 0);    /* 寫寄存器的命令, 併發送寄存器地址 */
        ADS1256_Send8Bit(0x03);            /* 寄存器個數 - 1, 此處3表示寫4個寄存器 */
        
        ADS1256_Send8Bit(buf[0]);    /* 設置狀態寄存器 */
        ADS1256_Send8Bit(buf[1]);    /* 設置輸入通道參數 */
        ADS1256_Send8Bit(buf[2]);    /* 設置ADCON控制寄存器,增益 */
        ADS1256_Send8Bit(buf[3]);    /* 設置輸出數據速率 */
        
        CS_1();    /* SPI片選 = 1 */        
    }

    bsp_DelayUS(50);    
}

這個函數主要配置了4個ADS1256寄存器。

  •   設置狀態寄存器:

 

 

程序中的配置爲:buf[0] = (0 << 3) | (1 << 2) | (1 << 1) ,意思是LSB傳輸,自動校準,使能模擬輸入緩衝。

  •   設置輸入通道參數

 

 

程序中的配置爲:buf[1] = 0x08, 高四位0表示AINp接通的 AIN0,  低四位8表示 AINn接通的 AINCOM。AINp和AINn表示當前的多路選擇器選通的AIN0:

 

 

  •   設置ADCON控制寄存器,主要用於增益設置

 

 

程序中的配置爲:buf[2] = (0 << 5) | (0 << 2) | (_gain << 1), 意思是關閉CLKOUT引腳輸出,關閉傳感器檢測,設置增益爲形參_gain。

  •   設置ADC採樣率

 

 

程序中的配置爲:buf[3] = s_tabDataRate[_drate],用於設置波特率:

static const uint8_t s_tabDataRate[ADS1256_DRATE_MAX] = 
{
    0xF0,        /* 復位時缺省值 */
    0xE0,
    0xD0,
    0xC0,
    0xB0,
    0xA1,
    0x92,
    0x82,
    0x72,
    0x63,
    0x53,
    0x43,
    0x33,
    0x20,
    0x13,
    0x03
};
typedef enum
{
    ADS1256_30000SPS = 0,
    ADS1256_15000SPS,
    ADS1256_7500SPS,
    ADS1256_3750SPS,
    ADS1256_2000SPS,
    ADS1256_1000SPS,
    ADS1256_500SPS,
    ADS1256_100SPS,
    ADS1256_60SPS,
    ADS1256_50SPS,
    ADS1256_30SPS,
    ADS1256_25SPS,
    ADS1256_15SPS,
    ADS1256_10SPS,
    ADS1256_5SPS,
    ADS1256_2d5SPS,
    
    ADS1256_DRATE_MAX
}ADS1256_DRATE_E;

93.5.5 第4步,ADS1256啓動採樣

代碼實現如下

/*
*********************************************************************************************************
*    函 數 名: ADS1256_StartScan
*    功能說明: 將 DRDY引腳 (PC6 )配置成外部中斷觸發方式, 中斷服務程序中掃描8個通道的數據。
*    形    參: 無
*    返 回 值: 無
*********************************************************************************************************
*/
void ADS1256_StartScan(void)
{
    /* PC6 外部中斷,BUSY 
        配置 BUSY 作爲中斷輸入口,下降沿觸發 */
    {
        GPIO_InitTypeDef   GPIO_InitStructure;
        
        DRDY_CLK_ENABLE();    /* 打開GPIO時鐘 */

        GPIO_InitStructure.Mode = GPIO_MODE_IT_FALLING;
        GPIO_InitStructure.Pull = GPIO_NOPULL;
        GPIO_InitStructure.Pin = DRDY_PIN;
        HAL_GPIO_Init(DRDY_GPIO, &GPIO_InitStructure);    

        HAL_NVIC_SetPriority(DRDY_IRQn, 2, 0);
        HAL_NVIC_EnableIRQ(DRDY_IRQn);    
    }
    
    /* 開始掃描前, 清零結果緩衝區 */    
    {
        uint8_t i;
        
        g_tADS1256.Channel = 0;
        
        for (i = 0; i < 8; i++)
        {
            g_tADS1256.AdcNow[i] = 0;
        }    
    }
}

代碼比較簡單,主要是配置PC6的EXTI外部中斷,並初始化變量。

93.5.6 第5步,ADS1256的中斷處理(8通道數據讀取)

代碼如下:

/*
*********************************************************************************************************
*    函 數 名: EXTI9_5_IRQHandler
*    功能說明: 外部中斷服務程序.  此程序執行時間約 123uS
*    形    參:無
*    返 回 值: 無
*********************************************************************************************************
*/
#ifdef EXTI9_5_ISR_MOVE_OUT        /* bsp.h 中定義此行,表示本函數移到 stam32f4xx_it.c。 避免重複定義 */
void EXTI9_5_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_6);
}

/*
*********************************************************************************************************
*    函 數 名: EXTI9_5_IRQHandler
*    功能說明: 外部中斷服務程序入口。PI6 / AD7606_BUSY 下降沿中斷觸發
*    形    參: 無
*    返 回 值: 無
*********************************************************************************************************
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if (GPIO_Pin == GPIO_PIN_6)
    {

        ADS1256_ISR();
    }
}
#endif

/*
*********************************************************************************************************
*    函 數 名: ADS1256_ISR
*    功能說明: 定時採集中斷服務程序
*    形    參: 無
*    返 回 值: 無
*********************************************************************************************************
*/
void ADS1256_ISR(void)
{
    /* 讀取採集結構,保存在全局變量 */                    
    ADS1256_SetChannal(g_tADS1256.Channel);    /* 切換模擬通道 */    
    bsp_DelayUS(5);
    
    ADS1256_WriteCmd(CMD_SYNC);
    bsp_DelayUS(5);
    
    ADS1256_WriteCmd(CMD_WAKEUP);
    bsp_DelayUS(25);
    
    if (g_tADS1256.Channel == 0)
    {
        g_tADS1256.AdcNow[7] = ADS1256_ReadData();    /* 注意保存的是上一個通道的數據 */
    }
    else
    {
        g_tADS1256.AdcNow[g_tADS1256.Channel-1] = ADS1256_ReadData(); /* 注意保存的是上一個通道的數據 */
    }
                
    if (++g_tADS1256.Channel >= 8)
    {
        g_tADS1256.Channel = 0;
    }
}

中斷服務程序的代碼完全是按照下面的時序時序:

 

 

  •   第1步:ADS1256_SetChannal(g_tADS1256.Channel)切換模擬通道。
  •   第2步:發送SYNC同步命令。
  •   第3步:喚醒。
  •   第4步:讀取數據。

這個過程中特別注意讀取的是上次轉換的數據。

93.6 ADS1256板級支持包(bsp_spi_ads1256.c)

ADS1256驅動文件bsp_spi_ads1256.c主要實現瞭如下幾個API供用戶調用:

  •   bsp_InitADS1256
  •   ADS1256_CfgADC
  •   ADS1256_StartScan
  •   ADS1256_SetChannal
  •   ADS1256_SetDiffChannal

93.6.1 函數bsp_InitADS1256

函數原型:

void bsp_InitADS1256(void)

函數描述:

主要用於ADS1256的初始化。

93.6.2 函數ADS1256_CfgADC

函數原型:

void ADS1256_CfgADC(ADS1256_GAIN_E _gain, ADS1256_DRATE_E _drate)

函數描述:

用於配置ADS1256的增益和採樣率。

函數參數:

  •   第1個參數用於設置增益,支持的參數如下:

ADS1256_GAIN_1

ADS1256_GAIN_2     

ADS1256_GAIN_4

ADS1256_GAIN_8

ADS1256_GAIN_16

ADS1256_GAIN_32

ADS1256_GAIN_64

  •   第2個參數用於設置採樣率,支持的參數如下:

ADS1256_30000SPS

ADS1256_15000SPS

ADS1256_7500SPS

ADS1256_3750SPS

ADS1256_2000SPS

ADS1256_1000SPS

ADS1256_500SPS

ADS1256_100SPS

ADS1256_60SPS

ADS1256_50SPS

ADS1256_30SPS

ADS1256_25SPS

ADS1256_15SPS

ADS1256_10SPS

ADS1256_5SPS

ADS1256_2d5SPS

93.6.3 函數ADS1256_StartScan

函數原型:

void ADS1256_StartScan(void)

函數描述:

此函數用於啓動掃描,採樣的中斷方式。

93.6.4 函數ADS1256_SetChannal

函數原型:

static void ADS1256_SetChannal(uint8_t _ch)

函數描述:

此函數用於設置單端採樣的通道。

函數參數:

  •   第1個參數支持0到7,0表示採樣的通道0, 1表示採樣的通道1,依次類推,範圍0-7,共8個通道。

 

93.7 ADS1256實際測量效果(10uV抖動)

測試LM285-2.5V穩壓效果,抖動40uV:

 

 

測試乾電池效果,抖動10uV左右,注意,這個級別的抖動容易受環境溫度的影響,特別是開關空調,最明顯。

 

 

93.8 ADS1256驅動移植和使用

移植步驟如下:

  •   第1步:複製bsp_spi_ads1256.c和bsp_spi_ads1256.h到自己的工程目錄,並添加到工程裏面。
  •   第2步:根據使用的SPI引腳,DRDY就緒引腳,RST復位引腳,修改bsp_spi_ads1256.c開頭的宏定義。
/* 定義GPIO端口 */    
#define SCK_CLK_ENABLE()     __HAL_RCC_GPIOA_CLK_ENABLE()
#define SCK_GPIO            GPIOA
#define SCK_PIN                GPIO_PIN_4
#define SCK_1()                SCK_GPIO->BSRR = SCK_PIN
#define SCK_0()                SCK_GPIO->BSRR = ((uint32_t)SCK_PIN << 16U)    

#define DIN_CLK_ENABLE()     __HAL_RCC_GPIOG_CLK_ENABLE()
#define DIN_GPIO            GPIOG
#define DIN_PIN                GPIO_PIN_10
#define DIN_1()                DIN_GPIO->BSRR = DIN_PIN
#define DIN_0()                DIN_GPIO->BSRR = ((uint32_t)DIN_PIN << 16U)    

#define CS_CLK_ENABLE()     __HAL_RCC_GPIOC_CLK_ENABLE()
#define CS_GPIO                GPIOC
#define CS_PIN                GPIO_PIN_7
#define CS_1()                CS_GPIO->BSRR = CS_PIN
#define CS_0()                CS_GPIO->BSRR = ((uint32_t)CS_PIN << 16U)    

#define DOUT_CLK_ENABLE()     __HAL_RCC_GPIOA_CLK_ENABLE()
#define DOUT_GPIO            GPIOA
#define DOUT_PIN            GPIO_PIN_5
#define DOUT_IS_HIGH()        ((DOUT_GPIO->IDR & DOUT_PIN) != 0)

#define DRDY_CLK_ENABLE()     __HAL_RCC_GPIOC_CLK_ENABLE()
#define DRDY_GPIO            GPIOC
#define DRDY_PIN            GPIO_PIN_6
#define DRDY_IS_LOW()        ((DRDY_GPIO->IDR & DRDY_PIN) == 0)
#define DRDY_IRQn             EXTI9_5_IRQn
#define DRDY_IRQHandler        EXTI9_5_IRQHandler    

/* PDWN  <------  PB7       掉電控制 */
#define PWDN_CLK_ENABLE()     __HAL_RCC_GPIOB_CLK_ENABLE()
#define PWDN_GPIO            GPIOB
#define PWDN_PIN            GPIO_PIN_7
#define PWDN_1()            PWDN_GPIO->BSRR = PWDN_PIN
#define PWDN_0()            PWDN_GPIO->BSRR = ((uint32_t)PWDN_PIN << 16U)            

/*  RST   <------  PC3       復位信號     */
#define RST_CLK_ENABLE()     __HAL_RCC_GPIOC_CLK_ENABLE()
#define RST_GPIO            GPIOC
#define RST_PIN                GPIO_PIN_3
#define RST_1()                RST_GPIO->BSRR = RST_PIN
#define RST_0()                RST_GPIO->BSRR = ((uint32_t)RST_PIN << 16U)    
  •   第3步:特別注意中斷服務程序的入口要根據使用的DRDY引腳修改。
/*
*********************************************************************************************************
*    函 數 名: EXTI9_5_IRQHandler
*    功能說明: 外部中斷服務程序.  此程序執行時間約 123uS
*    形    參:無
*    返 回 值: 無
*********************************************************************************************************
*/
#ifdef EXTI9_5_ISR_MOVE_OUT        /* bsp.h 中定義此行,表示本函數移到 stam32f4xx_it.c。 避免重複定義 */
void EXTI9_5_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_6);
}

/*
*********************************************************************************************************
*    函 數 名: EXTI9_5_IRQHandler
*    功能說明: 外部中斷服務程序入口。PI6 / AD7606_BUSY 下降沿中斷觸發
*    形    參: 無
*    返 回 值: 無
*********************************************************************************************************
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if (GPIO_Pin == GPIO_PIN_6)
    {

        ADS1256_ISR();
    }
}
#endif
  •   第4步:應用方法看本章節配套例子即可。

93.9 實驗例程設計框架

通過程序設計框架,讓大家先對配套例程有一個全面的認識,然後再理解細節,本次實驗例程的設計框架如下:

 

 

  第1階段,上電啓動階段:

  • 這部分在第14章進行了詳細說明。

  第2階段,進入main函數:

  •   第1部分,硬件初始化,主要是MPU,Cache,HAL庫,系統時鐘,滴答定時器和LED。
  •   第2部分,應用程序設計部分,測試ADS1256。

93.10          實驗例程說明(MDK)

配套例子:

V7-068_ADS1256(8通道帶PGA的24位ADC)

實驗目的:

  1. 學習ADS1256, 8通道帶PGA的24bit ADC。

重要提示:

  1. 開發板請使用外置電源供電。

實驗內容:

  1. 啓動一個自動重裝軟件定時器,每100ms翻轉一次LED2。
  2. 上電後插入ADS1256模塊到右上角CN26(2*6P雙排母), 程序每1秒打印一次8通道採樣數據。

上電後串口打印的信息:

波特率 115200,數據位 8,奇偶校驗位無,停止位 1。

 

 

模塊插入位置:

 

 

程序設計:

  系統棧大小分配:

 

 

  RAM空間用的DTCM:

 

 

  硬件外設初始化

硬件外設的初始化是在 bsp.c 文件實現:

/*
*********************************************************************************************************
*    函 數 名: bsp_Init
*    功能說明: 初始化所有的硬件設備。該函數配置CPU寄存器和外設的寄存器並初始化一些全局變量。只需要調用一次
*    形    參:無
*    返 回 值: 無
*********************************************************************************************************
*/
void bsp_Init(void)
{
    /* 配置MPU */
    MPU_Config();
    
    /* 使能L1 Cache */
    CPU_CACHE_Enable();

    /* 
       STM32H7xx HAL 庫初始化,此時系統用的還是H7自帶的64MHz,HSI時鐘:
       - 調用函數HAL_InitTick,初始化滴答時鐘中斷1ms。
       - 設置NVIV優先級分組爲4。
     */
    HAL_Init();

    /* 
       配置系統時鐘到400MHz
       - 切換使用HSE。
       - 此函數會更新全局變量SystemCoreClock,並重新配置HAL_InitTick。
    */
    SystemClock_Config();

    /* 
       Event Recorder:
       - 可用於代碼執行時間測量,MDK5.25及其以上版本才支持,IAR不支持。
       - 默認不開啓,如果要使能此選項,務必看V7開發板用戶手冊第xx章
    */    
#if Enable_EventRecorder == 1  
    /* 初始化EventRecorder並開啓 */
    EventRecorderInitialize(EventRecordAll, 1U);
    EventRecorderStart();
#endif
    
bsp_InitDWT();      /* 初始化DWT時鐘週期計數器 */       
    bsp_InitKey();         /* 按鍵初始化,要放在滴答定時器之前,因爲按鈕檢測是通過滴答定時器掃描 */
    bsp_InitTimer();       /* 初始化滴答定時器 */
    bsp_InitLPUart();     /* 初始化串口 */
    bsp_InitExtIO();     /* 初始化FMC總線74HC574擴展IO. 必須在 bsp_InitLed()前執行 */    
    bsp_InitLed();         /* 初始化LED */    
bsp_InitExtSDRAM(); /* 初始化SDRAM */
}

  MPU配置和Cache配置:

數據Cache和指令Cache都開啓。配置了AXI SRAM區(本例子未用到AXI SRAM)和FMC的擴展IO區。

/*
*********************************************************************************************************
*    函 數 名: MPU_Config
*    功能說明: 配置MPU
*    形    參: 無
*    返 回 值: 無
*********************************************************************************************************
*/
static void MPU_Config( void )
{
    MPU_Region_InitTypeDef MPU_InitStruct;

    /* 禁止 MPU */
    HAL_MPU_Disable();

    /* 配置AXI SRAM的MPU屬性爲Write back, Read allocate,Write allocate */
    MPU_InitStruct.Enable           = MPU_REGION_ENABLE;
    MPU_InitStruct.BaseAddress      = 0x24000000;
    MPU_InitStruct.Size             = MPU_REGION_SIZE_512KB;
    MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;
    MPU_InitStruct.IsCacheable      = MPU_ACCESS_CACHEABLE;
    MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;
    MPU_InitStruct.Number           = MPU_REGION_NUMBER0;
    MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL1;
    MPU_InitStruct.SubRegionDisable = 0x00;
    MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;

    HAL_MPU_ConfigRegion(&MPU_InitStruct);
    
    
    /* 配置FMC擴展IO的MPU屬性爲Device或者Strongly Ordered */
    MPU_InitStruct.Enable           = MPU_REGION_ENABLE;
    MPU_InitStruct.BaseAddress      = 0x60000000;
    MPU_InitStruct.Size             = ARM_MPU_REGION_SIZE_64KB;    
    MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;
    MPU_InitStruct.IsCacheable      = MPU_ACCESS_NOT_CACHEABLE;    
    MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;
    MPU_InitStruct.Number           = MPU_REGION_NUMBER1;
    MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL0;
    MPU_InitStruct.SubRegionDisable = 0x00;
    MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;
    
    HAL_MPU_ConfigRegion(&MPU_InitStruct);

    /*使能 MPU */
    HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}

/*
*********************************************************************************************************
*    函 數 名: CPU_CACHE_Enable
*    功能說明: 使能L1 Cache
*    形    參: 無
*    返 回 值: 無
*********************************************************************************************************
*/
static void CPU_CACHE_Enable(void)
{
    /* 使能 I-Cache */
    SCB_EnableICache();

    /* 使能 D-Cache */
    SCB_EnableDCache();
}

  每10ms調用一次按鍵處理:

按鍵處理是在滴答定時器中斷裏面實現,每10ms執行一次檢測。

/*
*********************************************************************************************************
*    函 數 名: bsp_RunPer10ms
*    功能說明: 該函數每隔10ms被Systick中斷調用1次。詳見 bsp_timer.c的定時中斷服務程序。一些處理時間要求
*              不嚴格的任務可以放在此函數。比如:按鍵掃描、蜂鳴器鳴叫控制等。
*    形    參: 無
*    返 回 值: 無
*********************************************************************************************************
*/
void bsp_RunPer10ms(void)
{
    bsp_KeyScan10ms();
}

  主功能:

主程序實現如下操作:

  •   啓動一個自動重裝軟件定時器,每100ms翻轉一次LED2。
  •   上電後插入ADS1256模塊到右上角CN26(2*6P雙排母), 程序每1秒打印一次8通道採樣數據。
/*
*********************************************************************************************************
*    函 數 名: main
*    功能說明: c程序入口
*    形    參: 無
*    返 回 值: 錯誤代碼(無需處理)
*********************************************************************************************************
*/
int main(void)
{
    uint8_t i;
    int32_t iTemp;
    float fTemp;

    
    bsp_Init();        /* 硬件初始化 */
    PrintfLogo();    /* 打印例程信息到串口1 */

    PrintfHelp();    /* 打印操作提示信息 */
    
    
    bsp_DelayMS(500);    /* 等待上電穩定,等基準電壓電路穩定, bsp_InitADS1256() 內部會進行自校準 */

    bsp_InitADS1256();    /* 初始化配置ADS1256.  PGA=1, DRATE=30KSPS, BUFEN=1, 輸入正負5V */
    
    
    /* 打印芯片ID (通過讀ID可以判斷硬件接口是否正常) , 正常時狀態寄存器的高4bit = 3 */
#if 0
    {
        uint8_t id;

        id = ADS1256_ReadChipID();

        if (id != 3)
        {
            printf("Error, ASD1256 Chip ID = 0x%X\r\n", id);
        }
        else
        {
            printf("Ok, ASD1256 Chip ID = 0x%X\r\n", id);
        }
    }
#endif
    
    ADS1256_CfgADC(ADS1256_GAIN_1, ADS1256_30SPS);    /* 配置ADC參數: 增益1:1, 數據輸出速率 30Hz */

/* 啓動中斷掃描模式, 輪流採集8個通道的ADC數據. 通過 ADS1256_GetAdc() 函數來讀取這些數據 */
    ADS1256_StartScan();    
    
    bsp_StartAutoTimer(0, 1000);    /* 啓動1個100ms的自動重裝的定時器 */

    /* 進入主程序循環體 */
    while (1)
    {
        bsp_Idle();        /* 這個函數在bsp.c文件。用戶可以修改這個函數實現CPU休眠和餵狗 */
        

        if (bsp_CheckTimer(0))    /* 判斷定時器超時時間 */
        {
            /* 每隔1000ms 進來一次 */
            bsp_LedToggle(2);    /* 翻轉LED的狀態 */
            
            /* 打印採集數據 */
            for (i = 0; i < 8; i++)
            {

                  /*
                    計算公式:2 * VREF/(PGA * (2^23 - 1)) ,這裏VREF是2.5V,PGA = 1
                  */
                   /* 計算實際電壓值(近似估算的),如需準確,請進行校準 */
                iTemp = ((int64_t)g_tADS1256.AdcNow[i] * 2500000) / 4194303; 

                
                fTemp = (float)iTemp / 1000000;   

                printf("CH%d=%07d(%fV) ", i, g_tADS1256.AdcNow[i], fTemp);

                if(i == 3)
                {
                    printf("\r\n");
                }
            }
            
            printf("\r\n\r\n");
        }
    }
}

93.11          實驗例程說明(IAR)

配套例子:

V7-068_ADS1256(8通道帶PGA的24位ADC)

實驗目的:

  1. 學習ADS1256, 8通道帶PGA的24bit ADC。

重要提示:

  1. 開發板請使用外置電源供電。

實驗內容:

  1. 啓動一個自動重裝軟件定時器,每100ms翻轉一次LED2。
  2. 上電後插入ADS1256模塊到右上角CN26(2*6P雙排母), 程序每1秒打印一次8通道採樣數據。

上電後串口打印的信息:

波特率 115200,數據位 8,奇偶校驗位無,停止位 1。

 

 

模塊插入位置:

 

 

程序設計:

  系統棧大小分配:

 

 

  RAM空間用的DTCM:

 

 

  硬件外設初始化

硬件外設的初始化是在 bsp.c 文件實現:

/*
*********************************************************************************************************
*    函 數 名: bsp_Init
*    功能說明: 初始化所有的硬件設備。該函數配置CPU寄存器和外設的寄存器並初始化一些全局變量。只需要調用一次
*    形    參:無
*    返 回 值: 無
*********************************************************************************************************
*/
void bsp_Init(void)
{
    /* 配置MPU */
    MPU_Config();
    
    /* 使能L1 Cache */
    CPU_CACHE_Enable();

    /* 
       STM32H7xx HAL 庫初始化,此時系統用的還是H7自帶的64MHz,HSI時鐘:
       - 調用函數HAL_InitTick,初始化滴答時鐘中斷1ms。
       - 設置NVIV優先級分組爲4。
     */
    HAL_Init();

    /* 
       配置系統時鐘到400MHz
       - 切換使用HSE。
       - 此函數會更新全局變量SystemCoreClock,並重新配置HAL_InitTick。
    */
    SystemClock_Config();

    /* 
       Event Recorder:
       - 可用於代碼執行時間測量,MDK5.25及其以上版本才支持,IAR不支持。
       - 默認不開啓,如果要使能此選項,務必看V7開發板用戶手冊第xx章
    */    
#if Enable_EventRecorder == 1  
    /* 初始化EventRecorder並開啓 */
    EventRecorderInitialize(EventRecordAll, 1U);
    EventRecorderStart();
#endif
    
bsp_InitDWT();      /* 初始化DWT時鐘週期計數器 */       
    bsp_InitKey();         /* 按鍵初始化,要放在滴答定時器之前,因爲按鈕檢測是通過滴答定時器掃描 */
    bsp_InitTimer();       /* 初始化滴答定時器 */
    bsp_InitLPUart();     /* 初始化串口 */
    bsp_InitExtIO();     /* 初始化FMC總線74HC574擴展IO. 必須在 bsp_InitLed()前執行 */    
    bsp_InitLed();         /* 初始化LED */    
bsp_InitExtSDRAM(); /* 初始化SDRAM */

    /* 針對不同的應用程序,添加需要的底層驅動模塊初始化函數 */    
    bsp_InitAD7606();    /* 配置AD7606所用的GPIO */
}

  MPU配置和Cache配置:

數據Cache和指令Cache都開啓。配置了AXI SRAM區(本例子未用到AXI SRAM)和FMC的擴展IO區。

/*
*********************************************************************************************************
*    函 數 名: MPU_Config
*    功能說明: 配置MPU
*    形    參: 無
*    返 回 值: 無
*********************************************************************************************************
*/
static void MPU_Config( void )
{
    MPU_Region_InitTypeDef MPU_InitStruct;

    /* 禁止 MPU */
    HAL_MPU_Disable();

    /* 配置AXI SRAM的MPU屬性爲Write back, Read allocate,Write allocate */
    MPU_InitStruct.Enable           = MPU_REGION_ENABLE;
    MPU_InitStruct.BaseAddress      = 0x24000000;
    MPU_InitStruct.Size             = MPU_REGION_SIZE_512KB;
    MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;
    MPU_InitStruct.IsCacheable      = MPU_ACCESS_CACHEABLE;
    MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;
    MPU_InitStruct.Number           = MPU_REGION_NUMBER0;
    MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL1;
    MPU_InitStruct.SubRegionDisable = 0x00;
    MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;

    HAL_MPU_ConfigRegion(&MPU_InitStruct);
    
    
    /* 配置FMC擴展IO的MPU屬性爲Device或者Strongly Ordered */
    MPU_InitStruct.Enable           = MPU_REGION_ENABLE;
    MPU_InitStruct.BaseAddress      = 0x60000000;
    MPU_InitStruct.Size             = ARM_MPU_REGION_SIZE_64KB;    
    MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;
    MPU_InitStruct.IsCacheable      = MPU_ACCESS_NOT_CACHEABLE;    
    MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;
    MPU_InitStruct.Number           = MPU_REGION_NUMBER1;
    MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL0;
    MPU_InitStruct.SubRegionDisable = 0x00;
    MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;
    
    HAL_MPU_ConfigRegion(&MPU_InitStruct);

    /*使能 MPU */
    HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}

/*
*********************************************************************************************************
*    函 數 名: CPU_CACHE_Enable
*    功能說明: 使能L1 Cache
*    形    參: 無
*    返 回 值: 無
*********************************************************************************************************
*/
static void CPU_CACHE_Enable(void)
{
    /* 使能 I-Cache */
    SCB_EnableICache();

    /* 使能 D-Cache */
    SCB_EnableDCache();
}

  每10ms調用一次按鍵處理:

按鍵處理是在滴答定時器中斷裏面實現,每10ms執行一次檢測。

/*
*********************************************************************************************************
*    函 數 名: bsp_RunPer10ms
*    功能說明: 該函數每隔10ms被Systick中斷調用1次。詳見 bsp_timer.c的定時中斷服務程序。一些處理時間要求
*              不嚴格的任務可以放在此函數。比如:按鍵掃描、蜂鳴器鳴叫控制等。
*    形    參: 無
*    返 回 值: 無
*********************************************************************************************************
*/
void bsp_RunPer10ms(void)
{
    bsp_KeyScan10ms();
}

  主功能:

主程序實現如下操作:

  •   啓動一個自動重裝軟件定時器,每100ms翻轉一次LED2。
  •   上電後插入ADS1256模塊到右上角CN26(2*6P雙排母), 程序每1秒打印一次8通道採樣數據。
/*
*********************************************************************************************************
*    函 數 名: main
*    功能說明: c程序入口
*    形    參: 無
*    返 回 值: 錯誤代碼(無需處理)
*********************************************************************************************************
*/
int main(void)
{
    uint8_t i;
    int32_t iTemp;
    float fTemp;

    
    bsp_Init();        /* 硬件初始化 */
    PrintfLogo();    /* 打印例程信息到串口1 */

    PrintfHelp();    /* 打印操作提示信息 */
    
    
    bsp_DelayMS(500);    /* 等待上電穩定,等基準電壓電路穩定, bsp_InitADS1256() 內部會進行自校準 */

    bsp_InitADS1256();    /* 初始化配置ADS1256.  PGA=1, DRATE=30KSPS, BUFEN=1, 輸入正負5V */
    
    
    /* 打印芯片ID (通過讀ID可以判斷硬件接口是否正常) , 正常時狀態寄存器的高4bit = 3 */
#if 0
    {
        uint8_t id;

        id = ADS1256_ReadChipID();

        if (id != 3)
        {
            printf("Error, ASD1256 Chip ID = 0x%X\r\n", id);
        }
        else
        {
            printf("Ok, ASD1256 Chip ID = 0x%X\r\n", id);
        }
    }
#endif
    
    ADS1256_CfgADC(ADS1256_GAIN_1, ADS1256_30SPS);    /* 配置ADC參數: 增益1:1, 數據輸出速率 30Hz */

/* 啓動中斷掃描模式, 輪流採集8個通道的ADC數據. 通過 ADS1256_GetAdc() 函數來讀取這些數據 */
    ADS1256_StartScan();    
    
    bsp_StartAutoTimer(0, 1000);    /* 啓動1個100ms的自動重裝的定時器 */

    /* 進入主程序循環體 */
    while (1)
    {
        bsp_Idle();        /* 這個函數在bsp.c文件。用戶可以修改這個函數實現CPU休眠和餵狗 */
        

        if (bsp_CheckTimer(0))    /* 判斷定時器超時時間 */
        {
            /* 每隔1000ms 進來一次 */
            bsp_LedToggle(2);    /* 翻轉LED的狀態 */
            
            /* 打印採集數據 */
            for (i = 0; i < 8; i++)
            {

                  /*
                    計算公式:2 * VREF/(PGA * (2^23 - 1)) ,這裏VREF是2.5V,PGA = 1
                  */
                   /* 計算實際電壓值(近似估算的),如需準確,請進行校準 */
                iTemp = ((int64_t)g_tADS1256.AdcNow[i] * 2500000) / 4194303; 

                
                fTemp = (float)iTemp / 1000000;   

                printf("CH%d=%07d(%fV) ", i, g_tADS1256.AdcNow[i], fTemp);

                if(i == 3)
                {
                    printf("\r\n");
                }
            }
            
            printf("\r\n\r\n");
        }
    }
}

93.12   總結

本章節涉及到的知識點非常多,主要爲大家講解了ADS1256的常用玩法,如果實際項目中用到此芯片需要熟練運用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章