1、工程创建
从gitee上下载rtthread完整版gitee-master分支(注意分支一定要选对)。
等待下载完成。
然后删除BSP文件夹下的板级支持包,仅留下nuvoton,并且将nuvoton文件夹下除了libraries和numaker-m2354其它都删除了,再然后将libraries下除了m2354和nu_packages以外的都删了。再然后回到numaker-m2354文件夹开始使用ENV工具。这里参照官网文档进行操作就可以了。或者你可以不了解,直接按照下述指令一条一条输入:
menuconfig --generate
pkgs --update
scons --target=mdk5(MDK5用户)或者scons --target=IAR(IAR用户)
我这里使用的是MDK5。
最后出现上述图片的内容就成功了。
2、工程裁剪
使用ENV工具,输入指令menuconfig,弹出如下界面。
这里不一一贴图了,高级功能都关了就可以。我工程中仅开启了串口(finsh)、ADC和ECAP功能(我的任务是EADC和ECAP)。
3、ADC底层代码
官方已经很贴心的实现了ADC的驱动层,drv_eadc.c,可实现ADC0的16个通道可选开起及关闭以及AD值读取功能。可以说是十分的贴心。
/* nu_adc_enabled - Enable ADC clock and wait for ready */
static rt_err_t nu_eadc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled)
{
EADC_T *eadc_base = ((nu_eadc_t)device)->eadc_base;
int *peadc_reg_tab = &((nu_eadc_t)device)->eadc_reg_tab;
RT_ASSERT(device != RT_NULL);
if (channel >= ((nu_eadc_t)device)->eadc_max_ch_num)
return -(RT_EINVAL);
if (enabled)
{
if (*peadc_reg_tab == 0)
{
EADC_Open(eadc_base, EADC_CTL_DIFFEN_SINGLE_END);
}
*peadc_reg_tab |= (0x1 << channel);
}
else
{
*peadc_reg_tab &= ~(0x1 << channel);
if (*peadc_reg_tab == 0)
{
EADC_Close(eadc_base);
}
}
return RT_EOK;
}
static rt_err_t nu_get_eadc_value(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value)
{
RT_ASSERT(device != RT_NULL);
RT_ASSERT(value != RT_NULL);
EADC_T *eadc_base = ((nu_eadc_t)device)->eadc_base;
int *peadc_reg_tab = &((nu_eadc_t)device)->eadc_reg_tab;
if (channel >= ((nu_eadc_t)device)->eadc_max_ch_num)
{
*value = 0xFFFFFFFF;
return -(RT_EINVAL);
}
if ((*peadc_reg_tab & (1 << channel)) == 0)
{
*value = 0xFFFFFFFF;
return -(RT_EBUSY);
}
EADC_ConfigSampleModule(eadc_base, 0, EADC_SOFTWARE_TRIGGER, channel);
EADC_CLR_INT_FLAG(eadc_base, EADC_STATUS2_ADIF0_Msk);
EADC_ENABLE_INT(eadc_base, BIT0);
EADC_ENABLE_SAMPLE_MODULE_INT(eadc_base, 0, BIT0);
EADC_START_CONV(eadc_base, BIT0);
while (EADC_GET_INT_FLAG(eadc_base, BIT0) == 0);
*value = EADC_GET_CONV_DATA(eadc_base, 0);
return RT_EOK;
}
4、ADC应用
使用官网提供的ADC测试代码,更改设备名称为eadc0,通道选择为6
#include <rtthread.h>
#include <rtdevice.h>
#define ADC_DEV_NAME "eadc0" /* ADC 设备名称 /
#define ADC_DEV_CHANNEL 6 / ADC 通道 /
#define REFER_VOLTAGE 300 / 参考电压 3.0V,数据精度乘以100保留2位小数*/
#define CONVERT_BITS (1 << 12) /* 转换位数为12位 */
static int adc_vol_sample(int argc, char argv[])
{
rt_adc_device_t adc_dev;
rt_uint32_t value, vol;
rt_err_t ret = RT_EOK;
/ 查找设备 /
adc_dev = (rt_adc_device_t)rt_device_find(ADC_DEV_NAME);
if (adc_dev == RT_NULL)
{
rt_kprintf("adc sample run failed! can't find %s device!\n", ADC_DEV_NAME);
return RT_ERROR;
}
/ 使能设备 /
ret = rt_adc_enable(adc_dev, ADC_DEV_CHANNEL);
/ 读取采样值 /
value = rt_adc_read(adc_dev, ADC_DEV_CHANNEL);
rt_kprintf("the value is :%d \n", value);
/ 转换为对应电压值 /
vol = value * REFER_VOLTAGE / CONVERT_BITS;
rt_kprintf("the voltage is :%d.%02d \n", vol / 100, vol % 100);
/ 关闭通道 /
ret = rt_adc_disable(adc_dev, ADC_DEV_CHANNEL);
return ret;
}
/ 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(adc_vol_sample, adc voltage convert sample);
5、测试
在FINSH控制台下,查看设备,eadc0已经在列表中了。
什么都不接的情况下测试ADC读取,此时ADC值为306,按照比照电压3V计算,此时为0.22V。
将ADC0_CH6与电源GND相连,此时ADC值为0。
测试完成。官方已经将基本的ADC设备驱动、框架搭建好了,十分的人性化,本人能力有限,如果文章中存在问题,请大家多多指教。
6、问题
我这个代码可以在KEIL下进行仿真,运行无问题,但是,断开仿真,重新上电,板子就不启动,目前还没发现为什么,希望有大佬指点一下。
原作者:werper