收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人
都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
/\*\*
\* @brief UART events handler.
\*/
void saadc\_callback(nrf\_drv\_saadc\_evt\_t const \* p_event){
}
/\*
saadc的初始化
\*/
void saadc\_init(void)
{
ret\_code\_t err_code;
/\*
使用默认配置配置saadc,可以根据自己需求修改配置
#define NRF\_DRV\_SAADC\_DEFAULT\_CHANNEL\_CONFIG\_SE \
NRFX\_SAADC\_DEFAULT\_CHANNEL\_CONFIG\_SE
\* @brief Macro for setting @ref nrf\_saadc\_channel\_config\_t to default settings
\* in single ended mode.
\*
\* @param PIN\_P Analog input.
#define NRFX\_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, \
.burst = NRF\_SAADC\_BURST\_DISABLED, \
.pin\_p = (nrf\_saadc\_input\_t)(PIN\_P), \
.pin\_n = NRF\_SAADC\_INPUT\_DISABLED \
}
上面各项内容的解释:
NRF\_SAADC\_RESISTOR\_DISABLED:这个是那个正端负端设置,怎么后面还有一个??
typedef enum
{
NRF\_SAADC\_RESISTOR\_DISABLED = SAADC\_CH\_CONFIG\_RESP\_Bypass, ///< Bypass resistor ladder.
NRF\_SAADC\_RESISTOR\_PULLDOWN = SAADC\_CH\_CONFIG\_RESP\_Pulldown, ///< Pull-down to GND.
NRF\_SAADC\_RESISTOR\_PULLUP = SAADC\_CH\_CONFIG\_RESP\_Pullup, ///< Pull-up to VDD.
NRF\_SAADC\_RESISTOR\_VDD1\_2 = SAADC\_CH\_CONFIG\_RESP\_VDD1\_2 ///< Set input at VDD/2.
} nrf\_saadc\_resistor\_t;
NRF\_SAADC\_GAIN1\_6:增益
typedef enum
{
NRF\_SAADC\_GAIN1\_6 = SAADC\_CH\_CONFIG\_GAIN\_Gain1\_6, ///< Gain factor 1/6.
NRF\_SAADC\_GAIN1\_5 = SAADC\_CH\_CONFIG\_GAIN\_Gain1\_5, ///< Gain factor 1/5.
NRF\_SAADC\_GAIN1\_4 = SAADC\_CH\_CONFIG\_GAIN\_Gain1\_4, ///< Gain factor 1/4.
NRF\_SAADC\_GAIN1\_3 = SAADC\_CH\_CONFIG\_GAIN\_Gain1\_3, ///< Gain factor 1/3.
NRF\_SAADC\_GAIN1\_2 = SAADC\_CH\_CONFIG\_GAIN\_Gain1\_2, ///< Gain factor 1/2.
NRF\_SAADC\_GAIN1 = SAADC\_CH\_CONFIG\_GAIN\_Gain1, ///< Gain factor 1.
NRF\_SAADC\_GAIN2 = SAADC\_CH\_CONFIG\_GAIN\_Gain2, ///< Gain factor 2.
NRF\_SAADC\_GAIN4 = SAADC\_CH\_CONFIG\_GAIN\_Gain4, ///< Gain factor 4.
} nrf\_saadc\_gain\_t;
NRF\_SAADC\_REFERENCE\_INTERNAL:参考电压
typedef enum
{
NRF\_SAADC\_REFERENCE\_INTERNAL = SAADC\_CH\_CONFIG\_REFSEL\_Internal, ///< Internal reference (0.6 V).
NRF\_SAADC\_REFERENCE\_VDD4 = SAADC\_CH\_CONFIG\_REFSEL\_VDD1\_4 ///< VDD/4 as reference.
} nrf\_saadc\_reference\_t;
NRF\_SAADC\_ACQTIME\_10US: 转换时间
typedef enum
{
NRF\_SAADC\_ACQTIME\_3US = SAADC\_CH\_CONFIG\_TACQ\_3us, ///< 3 us.
NRF\_SAADC\_ACQTIME\_5US = SAADC\_CH\_CONFIG\_TACQ\_5us, ///< 5 us.
NRF\_SAADC\_ACQTIME\_10US = SAADC\_CH\_CONFIG\_TACQ\_10us, ///< 10 us.
NRF\_SAADC\_ACQTIME\_15US = SAADC\_CH\_CONFIG\_TACQ\_15us, ///< 15 us.
NRF\_SAADC\_ACQTIME\_20US = SAADC\_CH\_CONFIG\_TACQ\_20us, ///< 20 us.
NRF\_SAADC\_ACQTIME\_40US = SAADC\_CH\_CONFIG\_TACQ\_40us ///< 40 us.
} nrf\_saadc\_acqtime\_t;
NRF\_SAADC\_MODE\_SINGLE\_ENDED:转换模式
typedef enum
{
NRF\_SAADC\_MODE\_SINGLE\_ENDED = SAADC\_CH\_CONFIG\_MODE\_SE, ///< Single ended, PSELN will be ignored, negative input to ADC shorted to GND.
NRF\_SAADC\_MODE\_DIFFERENTIAL = SAADC\_CH\_CONFIG\_MODE\_Diff ///< Differential mode.
} nrf\_saadc\_mode\_t;
NRF\_SAADC\_BURST\_DISABLED:这个是啥?
typedef enum
{
NRF\_SAADC\_BURST\_DISABLED = SAADC\_CH\_CONFIG\_BURST\_Disabled, ///< Burst mode is disabled (normal operation).
NRF\_SAADC\_BURST\_ENABLED = SAADC\_CH\_CONFIG\_BURST\_Enabled ///< Burst mode is enabled. SAADC takes 2^OVERSAMPLE number of samples as fast as it can, and sends the average to Data RAM.
} nrf\_saadc\_burst\_t;
(nrf\_saadc\_input\_t)(PIN\_P), :pin\_p 输入通道,根据自己的引脚选择
typedef enum
{
NRF\_SAADC\_INPUT\_DISABLED = SAADC\_CH\_PSELP\_PSELP\_NC, ///< Not connected.
NRF\_SAADC\_INPUT\_AIN0 = SAADC\_CH\_PSELP\_PSELP\_AnalogInput0, ///< Analog input 0 (AIN0).
NRF\_SAADC\_INPUT\_AIN1 = SAADC\_CH\_PSELP\_PSELP\_AnalogInput1, ///< Analog input 1 (AIN1).
NRF\_SAADC\_INPUT\_AIN2 = SAADC\_CH\_PSELP\_PSELP\_AnalogInput2, ///< Analog input 2 (AIN2).
NRF\_SAADC\_INPUT\_AIN3 = SAADC\_CH\_PSELP\_PSELP\_AnalogInput3, ///< Analog input 3 (AIN3).
NRF\_SAADC\_INPUT\_AIN4 = SAADC\_CH\_PSELP\_PSELP\_AnalogInput4, ///< Analog input 4 (AIN4).
NRF\_SAADC\_INPUT\_AIN5 = SAADC\_CH\_PSELP\_PSELP\_AnalogInput5, ///< Analog input 5 (AIN5).
NRF\_SAADC\_INPUT\_AIN6 = SAADC\_CH\_PSELP\_PSELP\_AnalogInput6, ///< Analog input 6 (AIN6).
NRF\_SAADC\_INPUT\_AIN7 = SAADC\_CH\_PSELP\_PSELP\_AnalogInput7, ///< Analog input 7 (AIN7).
NRF\_SAADC\_INPUT\_VDD = SAADC\_CH\_PSELP\_PSELP\_VDD ///< VDD as input.
} nrf\_saadc\_input\_t;
.pin\_n = NRF\_SAADC\_INPUT\_DISABLED 单端输入,这里DISABLED
\*/
nrf\_saadc\_channel\_config\_t channel_config =
NRF\_DRV\_SAADC\_DEFAULT\_CHANNEL\_CONFIG\_SE(NRF_SAADC_INPUT_AIN2);
/\*
初始化saadc
\_\_STATIC\_INLINE ret\_code\_t nrf\_drv\_saadc\_init(nrf\_drv\_saadc\_config\_t const \* p\_config,
nrf\_drv\_saadc\_event\_handler\_t event\_handler)
{
if (p\_config == NULL)
{
static const nrfx\_saadc\_config\_t default\_config = NRFX\_SAADC\_DEFAULT\_CONFIG;
p\_config = &default\_config;
}
return nrfx\_saadc\_init(p\_config, event\_handler);
}
NRFX\_SAADC\_DEFAULT\_CONFIG: 默认配置
\* @brief Macro for setting @ref nrfx\_saadc\_config\_t to default settings.
#define NRFX\_SAADC\_DEFAULT\_CONFIG \
{ \
.resolution = (nrf\_saadc\_resolution\_t)NRFX\_SAADC\_CONFIG\_RESOLUTION, \
.oversample = (nrf\_saadc\_oversample\_t)NRFX\_SAADC\_CONFIG\_OVERSAMPLE, \
.interrupt\_priority = NRFX\_SAADC\_CONFIG\_IRQ\_PRIORITY, \
.low\_power\_mode = NRFX\_SAADC\_CONFIG\_LP\_MODE \
}
NRFX\_SAADC\_CONFIG\_RESOLUTION:分辨率
#define NRFX\_SAADC\_CONFIG\_RESOLUTION SAADC\_CONFIG\_RESOLUTION
// <0=> 8 bit
// <1=> 10 bit
// <2=> 12 bit
// <3=> 14 bit
#ifndef SAADC\_CONFIG\_RESOLUTION
#define SAADC\_CONFIG\_RESOLUTION 1
#endif
NRFX\_SAADC\_CONFIG\_OVERSAMPLE: 这个是啥来着?反正就是
#define NRFX\_SAADC\_CONFIG\_OVERSAMPLE SAADC\_CONFIG\_OVERSAMPLE
// <0=> Disabled
// <1=> 2x
// <2=> 4x
// <3=> 8x
// <4=> 16x
// <5=> 32x
// <6=> 64x
// <7=> 128x
// <8=> 256x
#ifndef SAADC\_CONFIG\_OVERSAMPLE
#define SAADC\_CONFIG\_OVERSAMPLE 0
#endif
NRFX\_SAADC\_CONFIG\_IRQ\_PRIORITY: 中断优先级这个简单
NRFX\_SAADC\_CONFIG\_LP\_MODE: 低功耗模式
NULL表示使用默认配置
\*/
err_code = nrf\_drv\_saadc\_init(NULL, saadc_callback);
APP\_ERROR\_CHECK(err_code);
/\*
加入通道配置
#define nrf\_drv\_saadc\_channel\_init nrfx\_saadc\_channel\_init
nrfx\_err\_t nrfx\_saadc\_channel\_init(uint8\_t channel,
nrf\_saadc\_channel\_config\_t const \* const p\_config)
所以 0 是通道名字,通道0 ,通道参数是上面的配置
\*/
err_code = nrf\_drv\_saadc\_channel\_init(0, &channel_config);
APP\_ERROR\_CHECK(err_code);
}
/\*\*
\* @brief Function for main application entry.
\*/
int main(void)
{
nrf\_saadc\_value\_t saadc_val;
float val;
uint32\_t err_code = NRF\_LOG\_INIT(NULL);
APP\_ERROR\_CHECK(err_code);
NRF\_LOG\_DEFAULT\_BACKENDS\_INIT();
ret\_code\_t ret_code = nrf\_pwr\_mgmt\_init();
APP\_ERROR\_CHECK(ret_code);
NRF\_LOG\_INFO("rSAADC HAL simple example.");
//saadc初始化
saadc\_init();
while(1)
{
//启动一次ADC采样。
nrf\_drv\_saadc\_sample\_convert(0,&saadc_val);
/\*
ADC采样值
根据公式分辨率是10,所以2^10 = 1024
saadc\_val = val\* 1/6 / 0.6 \* 1024
\*/
val = saadc_val \* 3.6 /1024;
NRF\_LOG\_INFO(" %d mV",val\*1000);
NRF\_LOG\_FLUSH();
//延时300msSAADC采样一次
nrf\_delay\_ms(300);
nrf\_pwr\_mgmt\_run();
}
}
SAADC单次差分采样模式示例:
//...
void saadc\_init(void)
{
ret\_code\_t err_code;
/\*
使用的是2个通道的这个配置,其他都一样
#define NRFX\_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) \
}
\*/
nrf\_saadc\_channel\_config\_t channel_config =
NRF\_DRV\_SAADC\_DEFAULT\_CHANNEL\_CONFIG\_DIFFERENTIAL(NRF_SAADC_INPUT_AIN2,NRF_SAADC_INPUT_AIN0);
//saadc性能参数不用变
err_code = nrf\_drv\_saadc\_init(NULL, saadc_callback);
APP\_ERROR\_CHECK(err_code);
err_code = nrf\_drv\_saadc\_channel\_init(0, &channel_config);
APP\_ERROR\_CHECK(err_code);
}
/\*\*
\* @brief Function for main application entry.
\*/
int main(void)
{
nrf\_saadc\_value\_t saadc_val;
float val;
uint32\_t err_code = NRF\_LOG\_INIT(NULL);
APP\_ERROR\_CHECK(err_code);
NRF\_LOG\_DEFAULT\_BACKENDS\_INIT();
ret\_code\_t ret_code = nrf\_pwr\_mgmt\_init();
APP\_ERROR\_CHECK(ret_code);
NRF\_LOG\_INFO("rSAADC HAL simple example.");
saadc\_init();
while(1)
{
//启动一次ADC采样。
nrf\_drv\_saadc\_sample\_convert(0,&saadc_val);
/\*
串口输出ADC采样值
同样的参数,差分采样公司分辨率10 - 1 = 9
2^9 = 512;
测试的时候把AIN0 ,查表得知 P0.02 接GND
\*/
val = saadc_val \* 3.6 /512;
NRF\_LOG\_INFO(" %d mV",val\*1000);
NRF\_LOG\_FLUSH();
//延时300ms
nrf\_delay\_ms(300);
}
}
SAADC EasyDMA 缓冲采样示例
对EasyDMA采样方式说明:
- EasyDMA作为adc采样的专用通道,负责把采样数据发送给 RAM 内的结果寄存器 RESULT
- 根据 RESULT 内的 RESULT.PTR 寄存器和 RESULT.MAXCNT 寄存器,分别决定了数据指针和这个数据指针的大小
- 只有填满这个数据指针内所有的空间,才能出发中断把转换数据读出。
因此整个转换次数 = 通道数 * buff 缓冲大小
SAADC EasyDMA单缓冲
EasyDMA单缓冲单通道中断采样示例:
/\*
callback 函数的参数
#define nrf\_drv\_saadc\_evt\_t nrfx\_saadc\_evt\_t
typedef struct
{
nrfx\_saadc\_evt\_type\_t type; ///< Event type.
union
{
nrfx\_saadc\_done\_evt\_t done; ///< Data for @ref NRFX\_SAADC\_EVT\_DONE event.
nrfx\_saadc\_limit\_evt\_t limit; ///< Data for @ref NRFX\_SAADC\_EVT\_LIMIT event.
} data;
} nrfx\_saadc\_evt\_t;
typedef struct
{
nrf\_saadc\_value\_t \* p\_buffer; ///< Pointer to buffer with converted samples.
uint16\_t size; ///< Number of samples in the buffer.
} nrfx\_saadc\_done\_evt\_t;
typedef struct
{
uint8\_t channel; ///< Channel on which the limit was detected.
nrf\_saadc\_limit\_t limit\_type; ///< Type of limit detected.
} nrfx\_saadc\_limit\_evt\_t;
\*/
void saadc\_callback(nrf\_drv\_saadc\_evt\_t const \* p_event)
{
float val;
if (p_event->type == NRF_DRV_SAADC_EVT_DONE){
ret\_code\_t err_code;
/\*
再申请一个缓冲区,为下次采集的缓冲区
缓冲区的数值读出来就是上次采集的结果
\*/
err_code = nrf\_drv\_saadc\_buffer\_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER);
//err\_code = nrf\_drv\_saadc\_buffer\_convert(m\_buffer\_pool, SAMPLES\_IN\_BUFFER);
APP\_ERROR\_CHECK(err_code);
int i;
NRF\_LOG\_INFO("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;
NRF\_LOG\_INFO(" %d mV",val\*1000);
}
m_adc_evt_counter++;
}
}
void saadc\_init(void)
{
ret\_code\_t err_code;
nrf\_saadc\_channel\_config\_t channel_config =
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);
err_code = nrf\_drv\_saadc\_channel\_init(0, &channel_config);
APP\_ERROR\_CHECK(err_code);
/\*
配置申请一个缓冲区
#define SAMPLES\_IN\_BUFFER 1
static nrf\_saadc\_value\_t m\_buffer\_pool[SAMPLES\_IN\_BUFFER];
#define nrf\_drv\_saadc\_buffer\_convert nrfx\_saadc\_buffer\_convert
nrfx\_err\_t nrfx\_saadc\_buffer\_convert(nrf\_saadc\_value\_t \* p\_buffer, uint16\_t size)
\*/
err_code = nrf\_drv\_saadc\_buffer\_convert(m_buffer_pool,SAMPLES_IN_BUFFER);
APP\_ERROR\_CHECK(err_code);
}
/\*\*
\* @brief Function for main application entry.
\*/
int main(void)
{
uint32\_t err_code = NRF\_LOG\_INIT(NULL);
APP\_ERROR\_CHECK(err_code);
NRF\_LOG\_DEFAULT\_BACKENDS\_INIT();
ret\_code\_t ret_code = nrf\_pwr\_mgmt\_init();
APP\_ERROR\_CHECK(ret_code);
NRF\_LOG\_INFO("rSAADC HAL simple example.");
saadc\_init();
while(1)
{
/\*
启动一次ADC采样
启动后会进入回调函数
\*/
nrf\_drv\_saadc\_sample();
NRF\_LOG\_FLUSH();
nrf\_delay\_ms(300);
}
}
EasyDMA单缓冲双通道中断采样示例:
//...
void saadc\_callback(nrf\_drv\_saadc\_evt\_t const \* p_event)
{
float val;
if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
{
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;
NRF\_LOG\_INFO("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;
NRF\_LOG\_INFO(" %d mV",val\*1000);
}
m_adc_evt_counter++;
}
}
void saadc\_init(void)
{
//两个通道缓冲
ret\_code\_t err_code;
nrf\_saadc\_channel\_config\_t channel_0_config =
NRF\_DRV\_SAADC\_DEFAULT\_CHANNEL\_CONFIG\_SE(NRF_SAADC_INPUT_AIN2);
nrf\_saadc\_channel\_config\_t channel_1_config =
NRF\_DRV\_SAADC\_DEFAULT\_CHANNEL\_CONFIG\_SE(NRF_SAADC_INPUT_AIN0);
err_code = nrf\_drv\_saadc\_init(NULL, saadc_callback);
APP\_ERROR\_CHECK(err_code);
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);
/\*
#define SAMPLES\_IN\_BUFFER 6
buff为6,通道采样顺序是1,2,1,2,1,2 各3次采样完毕才会触发回调函数
\*/
err_code = nrf\_drv\_saadc\_buffer\_convert(m_buffer_pool,SAMPLES_IN_BUFFER);
APP\_ERROR\_CHECK(err_code);
}
//..main函数和上面示例一样
SAADC EasyDMA双缓冲
EasyDMA双缓冲说明
启动采样后数据首先进入缓冲区1,缓冲区1满了以后缓冲区1中的数据自动进入缓冲区2,然后新来的数据重新又进入缓冲区1
当两个缓冲区都有数据的时候引发中断 ,中断中输出缓冲数据2的内容
EasyDMA双缓冲双通道中断采样示例:
//...
void saadc\_callback(nrf\_drv\_saadc\_evt\_t const \* p_event)
{
float val;
if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
{
ret\_code\_t err_code;
![img](https://img-blog.csdnimg.cn/img_convert/0f0827dd8ee8c9300377d1bfb69a846a.png)
![img](https://img-blog.csdnimg.cn/img_convert/d716f605d38a191abb4165b1a3b1e047.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新**
**需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)**
**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618679757)**
saadc\_callback(nrf\_drv\_saadc\_evt\_t const \* p_event)
{
float val;
if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
{
ret\_code\_t err_code;
[外链图片转存中...(img-hnaiUZhJ-1715892039619)]
[外链图片转存中...(img-T9NCeQTO-1715892039619)]
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新**
**需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)**
**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618679757)**