nRF52832的SAADC


SAADC部分思維導圖

1ADC原理

1.1主要特點

1)8/10/12分辨率,使用過采樣可達到14位分辨率
2)多達8個通道
單端輸入時使用1個通道,2個通道可組成差分輸入
單端和差分輸入時均可配置為掃描模式
3)滿量程輸入范圍(0 to VDD)
參考芯片數據手冊

1.2功能概述

參考芯片數據手冊

1.3工作模式

1)單次模式
2)連續模式
使用ADC內部定時器實現定時采樣
使用nRF52832的通用定時器定時同PPI觸發采樣,實現連續采樣
3)掃描模式
當使能一個ADC通道,ADC工作於單次模式,當使能的通道數量大於1個,ADC進入掃描模式

2SAADC的應用步驟

2.1SAADC庫文件

2.2SAADC驅動的應用

1)阻塞模式
2)非阻塞模式
3)門限監測

3相關寄存器

4重要的庫函數

5DEMO

5.1阻塞模式-單端輸入采樣

SAADC初始化

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "app_uart.h"
#include "app_error.h"
#include "nrf_delay.h"
#include "nrf.h"
#include "bsp.h"
#include "app_uart.h"

#include "nrf_drv_saadc.h"

#define UART_TX_BUF_SIZE 256      //uart 發送軟件緩存大小(字節數)
#define UART_RX_BUF_SIZE 256      //uart 接收軟件緩存大小(字節數) 

//saadc回調函數
void saadc_callback(nrf_drv_saadc_evt_t const *p_event){}
//saadc初始化函數
void saadc_init(void)
{
	ret_code_t err_code;
	//定義SAADC初始化結構體
	//使用默認的宏初始化時需要指定該通道的模擬輸入引腳
	//具體的引腳分布參考數據手冊
	nrf_saadc_channel_config_t mmysaadc=
	    NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN2);
	//初始化SAADC,注冊事件回調函數,注意因為使用了阻塞模式
	//所以可以不用回調函數,但是nrf_drv_saadc_init()要求必須提供回調函數
	//所以這里要注冊回調函數,無論有沒有用到
	err_code=nrf_drv_saadc_init(NULL,saadc_callback);
	APP_ERROR_CHECK(err_code);
	//初始化SAADC通道0
	err_code = nrf_drv_saadc_channel_init(0, &mmysaadc);
    APP_ERROR_CHECK(err_code);
	
}
//uart事件回調函數
void uart_error_handle(app_uart_evt_t * p_event)
{
    if (p_event->evt_type == APP_UART_COMMUNICATION_ERROR)
    {
        APP_ERROR_HANDLER(p_event->data.error_communication);
    }
    else if (p_event->evt_type == APP_UART_FIFO_ERROR)
    {
        APP_ERROR_HANDLER(p_event->data.error_code);
    }
}
//初始化串口
void usart_init()
{
	uint32_t err_code;
    
	  //定義一個uart配置結構體
    const app_uart_comm_params_t comm_params =
    {
        RX_PIN_NUMBER,  //定義uart接收引腳
        TX_PIN_NUMBER,  //定義uart發送引腳
        RTS_PIN_NUMBER, //定義uart RTS引腳,注意流控關閉后雖然定義了RTS和CTS引腳,但是不起作用
        CTS_PIN_NUMBER, //定義uart CTS引腳 
        APP_UART_FLOW_CONTROL_DISABLED,   //關閉uart流控
        false,
        UART_BAUDRATE_BAUDRATE_Baud115200 //uart波特率
    };
    //初始化app uart,注冊uart事件回調函數
    APP_UART_FIFO_INIT(&comm_params,
                         UART_RX_BUF_SIZE,
                         UART_TX_BUF_SIZE,
                         uart_error_handle,
                         APP_IRQ_PRIORITY_LOWEST,
                         err_code);

    APP_ERROR_CHECK(err_code);	
	
}
/**********************************************************************************************
 * 描  述 : main函數
 * 入  參 : 無
 * 返回值 : 無
 ***********************************************************************************************/ 
int main(void)
{
	nrf_saadc_value_t saadc_val;
	float voltage=9.99;;  //轉化后的電壓值
	usart_init();  //初始化串口
    saadc_init();  //初始化SAADC
    while(true)	
	{
		//啟動一次ADC采樣
		nrf_drv_saadc_sample_convert(0,&saadc_val);
		voltage=(float)saadc_val*3.6/1024;
                printf("voltage=%f\n",voltage);
		nrf_delay_ms(300);  //延時300ms
		printf("saadc_val=V%d\n", saadc_val);

	}
}

SAADC初始化包括兩部分:SAADC驅動程序初始化,SAADC通道配置。nrf_drv_saadc.h中定義了兩個帶輸入參數的初始化宏

#define NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(PIN_P) \
{                                                      \
    .resistor_p = NRF_SAADC_RESISTOR_DISABLED,         \
    .resistor_n = NRF_SAADC_RESISTOR_DISABLED,         \
    .gain       = NRF_SAADC_GAIN1_6,                   \
    .reference  = NRF_SAADC_REFERENCE_INTERNAL,        \
    .acq_time   = NRF_SAADC_ACQTIME_10US,              \
    .mode       = NRF_SAADC_MODE_SINGLE_ENDED,         \
    .pin_p      = (nrf_saadc_input_t)(PIN_P),          \
    .pin_n      = NRF_SAADC_INPUT_DISABLED             \
}

注意1
初始化宏配置SAADC通道的參數如下
ADC輸入正極電阻配置:旁路電阻梯
ADC輸入負極電阻配置:旁路電阻梯
增益:1/6
參考電壓:內部0.6V
采樣時間:10US
模式:單端輸入
突發模式:禁止
ADC輸入正極連接的模擬輸入引腳
ADC輸入負極連接的模擬輸入引腳:不連接

注意2

err_code=nrf_drv_saadc_init(NULL,saadc_callback);

SAADC初始化函數nrf_drv_saadc_init(),如果沒有提供SAADC配置結構體即第一個參數為NULL,這時驅動會使用“sdk_config.h”文件默認參數配置SAADC

5.2阻塞模式-差分輸入采樣

SAADC初始化
//saadc初始化函數
void saadc_init(void)
{
	ret_code_t err_code;
	//定義SAADC初始化結構體
	//使用默認的宏初始化時需要指定該通道的模擬輸入引腳
	//具體的引腳分布參考數據手冊
	nrf_saadc_channel_config_t mmysaadc=
	    NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_DIFFERENTIAL(NRF_SAADC_INPUT_AIN2,NRF_SAADC_INPUT_AIN0);
	//初始化SAADC,注冊事件回調函數,注意因為使用了阻塞模式
	//所以可以不用回調函數,但是nrf_drv_saadc_init()要求必須提供回調函數
	//所以這里要注冊回調函數,無論有沒有用到
	err_code=nrf_drv_saadc_init(NULL,saadc_callback);
	APP_ERROR_CHECK(err_code);
	//初始化SAADC通道0
	err_code = nrf_drv_saadc_channel_init(0, &mmysaadc);
    APP_ERROR_CHECK(err_code);
	
}

NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_DIFFERENTIAL宏有兩個輸入參數,對應通道的正極模擬輸入引腳和負極模擬輸入引腳

#define NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_DIFFERENTIAL(PIN_P, PIN_N) \
{                                                                       \
    .resistor_p = NRF_SAADC_RESISTOR_DISABLED,                          \
    .resistor_n = NRF_SAADC_RESISTOR_DISABLED,                          \
    .gain       = NRF_SAADC_GAIN1_6,                                    \
    .reference  = NRF_SAADC_REFERENCE_INTERNAL,                         \
    .acq_time   = NRF_SAADC_ACQTIME_10US,                               \
    .mode       = NRF_SAADC_MODE_DIFFERENTIAL,                          \
    .pin_p      = (nrf_saadc_input_t)(PIN_P),                           \
    .pin_n      = (nrf_saadc_input_t)(PIN_N)                            \
}

主函數:

int main(void)
{
	nrf_saadc_value_t saadc_val;
	float voltage=9.99;;  //轉化后的電壓值
	usart_init();  //初始化串口
    saadc_init();  //初始化SAADC
    while(true)	
	{
		//啟動一次ADC采樣
		nrf_drv_saadc_sample_convert(0,&saadc_val);
		//這里saadc_val變成了差分值
		voltage=(float)saadc_val*3.6/1024;
                printf("voltage=%f\n",voltage);
		nrf_delay_ms(300);  //延時300ms
		printf("saadc_val=V%d\n", saadc_val);

	}
}

5.3非阻塞模式-單緩存采樣

//定義SAADC采樣數據緩存
//定義SAADC采樣緩存數組大小
//只有采樣結果存滿該緩存之后,才會產生SAADC采樣完成事件
#define SAMPLES_IN_BUFFER 1

//定義SAADC采樣緩存數組大小
nrf_saadc_value_t m_buffer_pool[SAMPLES_IN_BUFFER];
//定義該變量用來保存SAADC采樣的次數
static uint32_t m_adc_evt_counter;
//SAADC初始化函數
void saadc_init(void)
{
	ret_code_t err_code;
	//定義SAADC初始化結構體
	//使用默認的宏初始化時需要指定該通道的模擬輸入引腳
	//具體的引腳分布參考數據手冊
	nrf_saadc_channel_config_t mmysaadc=
	    NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN2);
	//初始化SAADC,注冊事件回調函數,
    //注意,本例使用的是非阻塞模式,非阻塞模式下,采樣完成后以事件
	//的方式通知應用程序,應用程序在事件回調函數中讀取采樣數據
	err_code=nrf_drv_saadc_init(NULL,saadc_callback);
	APP_ERROR_CHECK(err_code);
	//初始化SAADC通道0
	err_code = nrf_drv_saadc_channel_init(NULL, &mmysaadc);
    APP_ERROR_CHECK(err_code);
	
	//設置好緩存,等待應用程序啟動采樣
    err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool, SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);
	
}

nrf_drv_saadc_buffer_convert函數將SAADC工作於非阻塞模式,可將SAADC配置為就緒狀態,但是不會觸發采樣

ret_code_t nrf_drv_saadc_buffer_convert	(	
    nrf_saadc_value_t * 	buffer,
    uint16_t 	size 
)

Function for issuing conversion of data to the buffer.

Parameters:
[in]	buffer	Result buffer.
[in]	size	Buffer size in words.
//saadc回調函數
void saadc_callback(nrf_drv_saadc_evt_t const *p_event)
{
	float val;  //保存SAADC采樣數據計算的實際電壓值
	
	if(p_event->type == NRF_DRV_SAADC_EVT_DONE)  //Event generated when the buffer is filled with samples
	{
		ret_code_t err_code;
		//設置好緩存,為下一次采樣准備
		err_code=nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer,
		                                      SAMPLES_IN_BUFFER);
											  
		
		APP_ERROR_CHECK(err_code);
		
		int i;
		//串口打印采樣次數
		printf("ADC event number:%d\r\n",(int)m_adc_evt_counter);
		
		for(i=0;i<SAMPLES_IN_BUFFER;i++)
		{
			val=p_event->data.done.p_buffer[i]*3.6/1024;	
      printf("Voltage = %.3fV\r\n", val);			
		}
		
		//采樣次數加1
		m_adc_evt_counter++;
		
	}
	
}

5.4非阻塞模式-雙緩存采樣

5.5電池電壓采樣

5.6三個通道同時采樣-定時器觸發

//定義SAADC采樣緩存數組大小
#define SAMPLES_IN_BUFFER 3

//定義SAADC采樣緩存數組
static nrf_saadc_value_t m_buffer_pool[SAMPLES_IN_BUFFER];
/***********************************************************
*函數介紹:初始化SAADC
	        通道0 采集電位器電壓   P004
	        通道1 采集光敏電阻電壓 P002
	        通道2 采樣芯片供電電壓 不需要外接引腳
*輸入參數:
*輸出參數:
*返回值:無
************************************************************/
void saadc_init(void)
{
	ret_code_t err_code;
	//定義SAADC采樣通道0初始化配置結構體變量,並用默認參數初始化
	nrf_saadc_channel_config_t channel_0_config=
	    NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN2);
	channel_0_config.gain=NRF_SAADC_GAIN1_6;
	channel_0_config.reference=NRF_SAADC_REFERENCE_INTERNAL;  //使用內部的0.6V作為參考電壓
	
	
	//定義SAADC采樣通道1初始化配置結構體,並用默認參數初始化
		nrf_saadc_channel_config_t channel_1_config=
	    NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0);
	channel_1_config.gain=NRF_SAADC_GAIN1_6;
	channel_1_config.reference=NRF_SAADC_REFERENCE_INTERNAL;  //使用內部的0.6V作為參考電壓

	//定義SAADC采樣通道2初始化配置結構體
	nrf_saadc_channel_config_t channel_2_config=
	    NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(SAADC_CH_PSELP_PSELP_VDD);

	channel_2_config.gain=NRF_SAADC_GAIN1_6;
	channel_2_config.reference=NRF_SAADC_REFERENCE_INTERNAL;  //使用內部的0.6V作為參考電壓

	//初始化SAADC
	err_code=nrf_drv_saadc_init(NULL,saadc_callback);
  APP_ERROR_CHECK(err_code);
	
	//初始化SAADC的通道0
	err_code = nrf_drv_saadc_channel_init(0, &channel_0_config);
  APP_ERROR_CHECK(err_code);

  err_code = nrf_drv_saadc_channel_init(1, &channel_1_config);
  APP_ERROR_CHECK(err_code);

  err_code = nrf_drv_saadc_channel_init(2, &channel_2_config);
  APP_ERROR_CHECK(err_code);
	
	//使用雙緩存
	//設置好第一個緩存
	err_code=nrf_drv_saadc_buffer_convert(m_buffer_pool,SAMPLES_IN_BUFFER);
	APP_ERROR_CHECK(err_code);
//	//設置好第二個緩存
//	err_code=nrf_drv_saadc_buffer_convert(m_buffer_pool[1],SAMPLES_IN_BUFFER);
//	APP_ERROR_CHECK(err_code);
}

注意
三個通道采樣,分別配置為通道0,1,2

//saadc回調函數
void saadc_callback(nrf_drv_saadc_evt_t const *p_event)
{
	  ret_code_t err_code;
    float val;  //保存SAADC采樣數據計算的實際電壓值
	  if(p_event->type == NRF_DRV_SAADC_EVT_DONE)
		{
		    //設置好緩存,為下一次采樣做准備
			  err_code=nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer,
			                                        SAMPLES_IN_BUFFER);
			   APP_ERROR_CHECK(err_code);
			   //讀取采樣結果,使用串口發送
			   for(uint32_t i=0;i<SAMPLES_IN_BUFFER;i++)
			   {
			    val=p_event->data.done.p_buffer[i]*3.6/1024;	
//                printf("Voltage = %.3fV\r\n", val);
					 switch(i)
					 {
					    case 0:printf("AIN2=%f\r\n",val); break;
						case 1:printf("AIN0=%f\r\n",val); break;
						case 2:printf("VDD=%f\r\n",val); break;
						default:break;
					 }
			   }
		}
}
/**********************************************************************************************
 * 描  述 : main函數
 * 入  參 : 無
 * 返回值 : 無
 ***********************************************************************************************/ 
int main(void)
{
	nrf_saadc_value_t saadc_val;
	usart_init();  //初始化串口
  saadc_init();  //初始化SAADC
  timers_init(); //定時器初始化函數
	while(true)	
	{

	}
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM