1.目的
学习nrf51822模拟比较器
2.分析
模拟比较器,用于比较2个模拟信号的大小,
3.平台:
协议栈版本:SDK10.0.0
编译软件:keil 5.14
硬件平台:nrf51822最小系统
例子:SDK 10.0.0\examples\ble_peripheral\ble_app_uart\pca10028\s110\arm4
4.步骤
1.把SDK10.0\components\drivers_nrf\lpcomp 文件中的.c文件添加到目录如下,并添加对应的路径。
2.添加如下代码。
static void lpcomp_event_handler(nrf_lpcomp_event_t event):设置回调函数
void lpcomp_init(void)初始化比较器。比较器底层配置使用的使系统默认的。
if (p_config == NULL)
{
p_config = &m_default_config;
}
底层硬件配置:nrf_lpcomp_configure(&(p_config->hal) );
/** LPCOMP driver default configuration, including the LPCOMP HAL configuration. */
#define NRF_DRV_LPCONF_DEFAULT_CONFIG \
{ \
.hal = {LPCOMP_CONFIG_REFERENCE , LPCOMP_CONFIG_DETECTION}, \
.input = LPCOMP_CONFIG_INPUT, \
.interrupt_priority = LPCOMP_CONFIG_IRQ_PRIORITY \
}
这里设置设置参数有: ={
参考电压 ,检测方式}
配置对比的输入管脚,
中断优先级
/* LPCOMP */
#define LPCOMP_ENABLED 1
#if (LPCOMP_ENABLED == 1)
#define LPCOMP_CONFIG_REFERENCE NRF_LPCOMP_REF_SUPPLY_4_8
#define LPCOMP_CONFIG_DETECTION NRF_LPCOMP_DETECT_DOWN
#define LPCOMP_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW
#define LPCOMP_CONFIG_INPUT NRF_LPCOMP_INPUT_2
#endif
/**
* @enum nrf_lpcomp_ref_t
* @brief LPCOMP reference selection.
*/
typedef enum
{
#ifdef NRF51
NRF_LPCOMP_REF_SUPPLY_1_8 = LPCOMP_REFSEL_REFSEL_SupplyOneEighthPrescaling, /**< Use supply with a 1/8 prescaler as reference. */
NRF_LPCOMP_REF_SUPPLY_2_8 = LPCOMP_REFSEL_REFSEL_SupplyTwoEighthsPrescaling, /**< Use supply with a 2/8 prescaler as reference. */
NRF_LPCOMP_REF_SUPPLY_3_8 = LPCOMP_REFSEL_REFSEL_SupplyThreeEighthsPrescaling, /**< Use supply with a 3/8 prescaler as reference. */
NRF_LPCOMP_REF_SUPPLY_4_8 = LPCOMP_REFSEL_REFSEL_SupplyFourEighthsPrescaling, /**< Use supply with a 4/8 prescaler as reference. */
NRF_LPCOMP_REF_SUPPLY_5_8 = LPCOMP_REFSEL_REFSEL_SupplyFiveEighthsPrescaling, /**< Use supply with a 5/8 prescaler as reference. */
NRF_LPCOMP_REF_SUPPLY_6_8 = LPCOMP_REFSEL_REFSEL_SupplySixEighthsPrescaling, /**< Use supply with a 6/8 prescaler as reference. */
NRF_LPCOMP_REF_SUPPLY_7_8 = LPCOMP_REFSEL_REFSEL_SupplySevenEighthsPrescaling, /**< Use supply with a 7/8 prescaler as reference. */
#elif defined NRF52
NRF_LPCOMP_REF_SUPPLY_1_8 = LPCOMP_REFSEL_REFSEL_Ref1_8Vdd, /**< Use supply with a 1/8 prescaler as reference. */
NRF_LPCOMP_REF_SUPPLY_2_8 = LPCOMP_REFSEL_REFSEL_Ref2_8Vdd, /**< Use supply with a 2/8 prescaler as reference. */
NRF_LPCOMP_REF_SUPPLY_3_8 = LPCOMP_REFSEL_REFSEL_Ref3_8Vdd, /**< Use supply with a 3/8 prescaler as reference. */
NRF_LPCOMP_REF_SUPPLY_4_8 = LPCOMP_REFSEL_REFSEL_Ref4_8Vdd, /**< Use supply with a 4/8 prescaler as reference. */
NRF_LPCOMP_REF_SUPPLY_5_8 = LPCOMP_REFSEL_REFSEL_Ref5_8Vdd, /**< Use supply with a 5/8 prescaler as reference. */
NRF_LPCOMP_REF_SUPPLY_6_8 = LPCOMP_REFSEL_REFSEL_Ref6_8Vdd, /**< Use supply with a 6/8 prescaler as reference. */
NRF_LPCOMP_REF_SUPPLY_7_8 = LPCOMP_REFSEL_REFSEL_Ref7_8Vdd, /**< Use supply with a 7/8 prescaler as reference. */
NRF_LPCOMP_REF_SUPPLY_1_16 = LPCOMP_REFSEL_REFSEL_Ref1_16Vdd, /**< Use supply with a 1/16 prescaler as reference. */
NRF_LPCOMP_REF_SUPPLY_3_16 = LPCOMP_REFSEL_REFSEL_Ref1_16Vdd, /**< Use supply with a 3/16 prescaler as reference. */
NRF_LPCOMP_REF_SUPPLY_5_16 = LPCOMP_REFSEL_REFSEL_Ref1_16Vdd, /**< Use supply with a 5/16 prescaler as reference. */
NRF_LPCOMP_REF_SUPPLY_7_16 = LPCOMP_REFSEL_REFSEL_Ref1_16Vdd, /**< Use supply with a 7/16 prescaler as reference. */
NRF_LPCOMP_REF_SUPPLY_9_16 = LPCOMP_REFSEL_REFSEL_Ref1_16Vdd, /**< Use supply with a 9/16 prescaler as reference. */
NRF_LPCOMP_REF_SUPPLY_11_16 = LPCOMP_REFSEL_REFSEL_Ref1_16Vdd, /**< Use supply with a 11/16 prescaler as reference. */
NRF_LPCOMP_REF_SUPPLY_13_16 = LPCOMP_REFSEL_REFSEL_Ref1_16Vdd, /**< Use supply with a 13/16 prescaler as reference. */
NRF_LPCOMP_REF_SUPPLY_15_16 = LPCOMP_REFSEL_REFSEL_Ref1_16Vdd, /**< Use supply with a 15/16 prescaler as reference. */
#endif
NRF_LPCOMP_REF_EXT_REF0 = LPCOMP_REFSEL_REFSEL_ARef |
(LPCOMP_EXTREFSEL_EXTREFSEL_AnalogReference0 << 16), /**< External reference 0. */
NRF_LPCOMP_CONFIG_REF_EXT_REF1 = LPCOMP_REFSEL_REFSEL_ARef |
(LPCOMP_EXTREFSEL_EXTREFSEL_AnalogReference1 << 16), /**< External reference 1. */
} nrf_lpcomp_ref_t;
/**
* @enum nrf_lpcomp_input_t
* @brief LPCOMP input selection.
*/
typedef enum
{
NRF_LPCOMP_INPUT_0 = LPCOMP_PSEL_PSEL_AnalogInput0, /**< Input 0. */
NRF_LPCOMP_INPUT_1 = LPCOMP_PSEL_PSEL_AnalogInput1, /**< Input 1. */
NRF_LPCOMP_INPUT_2 = LPCOMP_PSEL_PSEL_AnalogInput2, /**< Input 2. */
NRF_LPCOMP_INPUT_3 = LPCOMP_PSEL_PSEL_AnalogInput3, /**< Input 3. */
NRF_LPCOMP_INPUT_4 = LPCOMP_PSEL_PSEL_AnalogInput4, /**< Input 4. */
NRF_LPCOMP_INPUT_5 = LPCOMP_PSEL_PSEL_AnalogInput5, /**< Input 5. */
NRF_LPCOMP_INPUT_6 = LPCOMP_PSEL_PSEL_AnalogInput6, /**< Input 6. */
NRF_LPCOMP_INPUT_7 = LPCOMP_PSEL_PSEL_AnalogInput7 /**< Input 7. */
} nrf_lpcomp_input_t;
/**
* @enum nrf_lpcomp_detect_t
* @brief LPCOMP detection type selection.
*/
typedef enum
{
NRF_LPCOMP_DETECT_CROSS = LPCOMP_ANADETECT_ANADETECT_Cross, /**< Generate ANADETEC on crossing, both upwards and downwards crossing. */
NRF_LPCOMP_DETECT_UP = LPCOMP_ANADETECT_ANADETECT_Up, /**< Generate ANADETEC on upwards crossing only. */
NRF_LPCOMP_DETECT_DOWN = LPCOMP_ANADETECT_ANADETECT_Down /**< Generate ANADETEC on downwards crossing only. */
} nrf_lpcomp_detect_t;
这里选择的是:电源电压的4/8 作为参考,
输入电压低于参考电压的时候,产生事件NRF_LPCOMP_EVENT_DOWN
中断优先级为低
模拟输入通道2作为模拟比较电压。
具体参考手册:nRF51_Series_Reference_manual v3.0 和 nRF51822_PS v3.1
下载地址:http://www.nordicsemi.com/eng/Products/Bluetooth-Smart-Bluetooth-low-energy/nRF51822
/**@brief Function for placing the application in low power state while waiting for events.
*/
void lpcomp_event_handler(nrf_lpcomp_event_t event)
{
if (event == NRF_LPCOMP_EVENT_READY)
{
SEGGER_RTT_printf(0,"\r\nNRF_LPCOMP_EVENT_READY\r\n");
}
if (event == NRF_LPCOMP_EVENT_DOWN)
{
SEGGER_RTT_printf(0,"\r\nNRF_LPCOMP_EVENT_DOWN\r\n");
}
if (event == NRF_LPCOMP_EVENT_UP)
{
SEGGER_RTT_printf(0,"\r\nNRF_LPCOMP_EVENT_UP\r\n");
}
}
/**
* @brief Initialize LPCOMP driver.
*/
void lpcomp_init(void)
{
uint32_t err_code;
// initialize LPCOMP driver, from this point LPCOMP will be active and provided
// event handler will be executed when defined action is detected
err_code = nrf_drv_lpcomp_init(NULL, lpcomp_event_handler);
APP_ERROR_CHECK(err_code);
nrf_drv_lpcomp_enable();
}
ret_code_t nrf_drv_lpcomp_init(const nrf_drv_lpcomp_config_t * p_config,
lpcomp_events_handler_t events_handler)
{
if (m_state != NRF_DRV_STATE_UNINITIALIZED)
{ // LPCOMP driver is already initialized
return NRF_ERROR_INVALID_STATE;
}
if (p_config == NULL)
{
p_config = &m_default_config;
}
nrf_lpcomp_configure(&(p_config->hal) );
if (events_handler)
{
m_lpcomp_events_handler = events_handler;
}
else
{
return NRF_ERROR_INVALID_PARAM;
}
nrf_lpcomp_input_select(p_config->input);
switch (p_config->hal.detection)
{
case NRF_LPCOMP_DETECT_UP:
nrf_lpcomp_int_enable(LPCOMP_INTENSET_UP_Msk);
break;
case NRF_LPCOMP_DETECT_DOWN:
nrf_lpcomp_int_enable(LPCOMP_INTENSET_DOWN_Msk);
break;
case NRF_LPCOMP_DETECT_CROSS:
nrf_lpcomp_int_enable(LPCOMP_INTENSET_CROSS_Msk);
break;
default:
break;
}
nrf_lpcomp_shorts_enable(NRF_LPCOMP_SHORT_READY_SAMPLE_MASK);
nrf_drv_common_irq_enable(LPCOMP_IRQn, p_config->interrupt_priority);
m_state = NRF_DRV_STATE_INITIALIZED;
return NRF_SUCCESS;
}
这个是,中断函数,会查找对应的标志位,并产生对应的回调。。
void LPCOMP_IRQHandler(void)
{
lpcomp_execute_handler(NRF_LPCOMP_EVENT_READY, LPCOMP_INTENSET_READY_Msk);
lpcomp_execute_handler(NRF_LPCOMP_EVENT_DOWN, LPCOMP_INTENSET_DOWN_Msk);
lpcomp_execute_handler(NRF_LPCOMP_EVENT_UP, LPCOMP_INTENSET_UP_Msk);
lpcomp_execute_handler(NRF_LPCOMP_EVENT_CROSS, LPCOMP_INTENSET_CROSS_Msk);
}
4.实验,把P02脚短接到地的时候:与配置,和回调函数一样。ok ye!!!