yang8555u 发表于 2022-7-27 00:45

【国民技术N32WB452测评】第二期、在RT-Thread完整版中点灯及ADC的使用

<div class='showpostmsg'> 本帖最后由 yang8555u 于 2022-7-27 13:35 编辑

上一次发帖,我曾经请教过论坛里的各位,想试图找到N32WB452的RT-Thread的完整版系统SDK,可惜收获的回答是No。在获得这个回答后,曾考虑过移植RT-Thread到N32WB452上,但发现,RTThread的官方移植的N32G457的SDK也是可以直接下到N32WB452里的,个人推测因为都是国民技术的芯片,且寄存器、处理器内核都是一样的,所以能通用。当然了,N32WB452对比N32G457,多出了蓝牙外设,蓝牙外设的有关例程暂时只支持keil,不支持RT-Thread Studio,我尝试移植蓝牙组件到RT-Thread SDK下使用,暂时没有成功,因为牵涉到太多文件的修改,这个就放在后期再做尝试。
回到主题,本期及后几期帖子,都会评测RT-Thead在N32WB452上的相关运行实验。
##一、创建工程
在RT-Thread官网,下载RT-Thread Studio,并在SDK管理器中,下载N32G45X的开发板支持包,如图所示:

下载完成后,即可创建RT-Thread新工程,如图:

##二、修改工程文件
在board.h中,修改FLASH大小为512,如图:

打开drv_gpio.c文件,将PIN_NUBERS一栏由64改为100,否则,某些引脚我们想使用的时候将找不到,如图:

##三、GPIO的使用
参考N32WB452的原理图,可以知道在开发板中央的四个LED灯D1/D10/D11/D12和轻触按钮K04的位号及对应连接的引脚,考虑到使用方便,我们将其在main.c中预先声明,如图:

可见我们已经声明了对应的引脚,这些对应数字的来源请参考drv_gpio.c中的定义。
接下来就是以RT-Thread的PIN设备的方法进行点灯,首先设置D12引脚为输出模式,然后在while循环中,不断重复引脚高电平与低电平。延时设定为200毫秒切换一次,如果需要修改,修改speed变量即可。D1/D10/D11点灯的方式与D12一致,便不再赘述。
##四、ADC的使用
关于RT-Thread的ADC,咱还没整明白,所以这部分依旧采用N32的官方库函数进行开发。
本次ADC的测量,是测量开发板板载的电位器的电压,电位器的位号为RP1,通过查询原理图,我们可以得知电位器的ADC测量引脚为PB2。
则在库函数中,初始化并配置PB2引脚,并以0.5秒的频率不断输出ADC的测量值,及对应转换的电压(不准,离万用表测量的电压有20-40mv的偏差)。
```c
#include <rtthread.h>
#include <rtdevice.h>
#include <stdio.h>
#define DBG_TAG "ADC"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
#include <n32g45x.h>
#define THREAD_PRIORITY         25
#define THREAD_STACK_SIZE       2048
#define THREAD_TIMESLICE      5
static rt_thread_t tid1 = RT_NULL;
ADC_InitType ADC_InitStructure;
uint16_t ADC_GetData(ADC_Module* ADCx, uint8_t ADC_Channel);
__IO uint16_t ADC2ConvertedValue;
#define ADC_CH_13 ((uint8_t)0x0D)
#define ADC_MODULE          ADC2
#define ADC_ENABLE_CLK()    (RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_ADC2, ENABLE))

#define ADC_ENABLE_PORTCLK()    (RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE))
#define ADC_PORT            GPIOB
#define ADC_PIN             GPIO_PIN_2
typedef enum adc_sample_ch_e
{
    ADC_SAMPLE_CH_ADC = ADC_CH_13, ///< PB2-定义ADC采样
    ADC_SAMPLE_CH_MAX
} adc_sample_ch;
void ADC_Config(ADC_Module *ADCx, adc_sample_ch ch)
{
    ADC_InitType ADC_InitStructure;
    GPIO_InitType GPIO_InitStructure;
    /* ADC2 Periph clock enable */
    ADC_ENABLE_CLK();
    ADC_ENABLE_PORTCLK();
    /* Configure ADC Channel11 as analog input */
    GPIO_InitStructure.Pin          = GPIO_PIN_2;
    GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_AIN;
    GPIO_InitStructure.GPIO_Speed   = GPIO_INPUT;
    GPIO_InitPeripheral(ADC_PORT, &GPIO_InitStructure);
    RCC_ConfigAdcPllClk(RCC_ADCPLLCLK_DIV6, ENABLE); //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
    /* ADCs DeInit */
    ADC_DeInit(ADCx);
    /* Initialize ADC structure */
    ADC_InitStruct(&ADC_InitStructure);
    /* Configure the ADC2 in continuous mode with a resolution equal to 12 bits*/
    ADC_InitStructure.WorkMode       = ADC_WORKMODE_INDEPENDENT; // ADC工作在独立模式
    ADC_InitStructure.MultiChEn      = DISABLE;                  //模数转换工作在单通道模式
    ADC_InitStructure.ContinueConvEn = DISABLE;                  //模数转换工作在单次转换模式
    ADC_InitStructure.ExtTrigSelect= ADC_EXT_TRIGCONV_NONE;    //转换由软件而不是外部触发启动
    ADC_InitStructure.DatAlign       = ADC_DAT_ALIGN_R;          // ADC数据右对齐
    ADC_InitStructure.ChsNumber      = 1;                        //顺序进行规则转换的ADC通道的数目
    ADC_Init(ADCx, &ADC_InitStructure);                        //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器
    ADC_Enable(ADCx, ENABLE); //使能指定的ADC2
    /*Check ADC Ready*/
    while(ADC_GetFlagStatusNew(ADCx,ADC_FLAG_RDY) == RESET);
    ADC_StartCalibration(ADCx); //开启AD校准
    while (ADC_GetCalibrationStatus(ADCx))
      ; //等待校准结束
}
uint16_t ADC_GetData(ADC_Module* ADCx, uint8_t ADC_Channel)
{
    uint16_t dat;
    ADC_ConfigRegularChannel(ADCx, ADC_Channel, 1, ADC_SAMP_TIME_239CYCLES5);
    /* Start ADC Software Conversion */
    ADC_EnableSoftwareStartConv(ADCx, ENABLE);
    while(ADC_GetFlagStatus(ADCx, ADC_FLAG_ENDC)==0){
    }
    ADC_ClearFlag(ADCx, ADC_FLAG_ENDC);
    ADC_ClearFlag(ADCx, ADC_FLAG_STR);
    dat=ADC_GetDat(ADCx);
    return dat;
}
static void adc_collect_thread_entry(void *parameter)
{
    double ADC_Volt=0.0;
    double ADC_Vrefint_Volt=0.0;
    rt_kprintf("ADC Init Start\n");
    ADC_Config(ADC_MODULE, ADC_SAMPLE_CH_ADC);
    rt_kprintf("ADC Init Success\n");
    ADC_EnableTempSensorVrefint(ENABLE);
    char str;
    while (1)
      {
      ADC2ConvertedValue=ADC_GetData(ADC2,ADC2_Channel_13_PB2);
      ADC_Volt=(double)ADC2ConvertedValue*3.267/4095;
      sprintf(str,"ADC Value is %d,ADC Volt is %d.%d",ADC2ConvertedValue,(int )ADC_Volt, (int )(ADC_Volt * 1000) % 1000);
      LOG_I("%s",str);
      rt_thread_mdelay(500);
    }

}
int adc_collect(void)
{
    /* 创建线程*/
    tid1 = rt_thread_create("adc_collect_thread", adc_collect_thread_entry, RT_NULL, THREAD_STACK_SIZE,
            THREAD_PRIORITY, THREAD_TIMESLICE);

    /* 如果获得线程控制块,启动这个线程 */
    if (tid1 != RT_NULL)
      rt_thread_startup(tid1);

    return 0;
}

```
在main.c中引用:
```c
#include <stdint.h>
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtthread.h>
#include <rtdevice.h>
#include <stdio.h>
#include <rtdbg.h>
#include <ulog.h>
/* defined the D1pin: PD0
* defined the D10 pin: PD1
* defined the D11 pin: PE2
* defined the D12 pin: PE3
**/
//extern int hdc2010_collect(void);
extern int hdc1080_collect(void);
extern int adc_collect(void);
#define D1_PIN      81
#define D10_PIN   82
#define D11_PIN   1
#define D12_PIN   2
#define K04_PIN   55
float i = 1.546;
int main(void)
{
    uint32_t Speed = 200;
    /* set D12 pin mode to output */
    rt_pin_mode(D12_PIN, PIN_MODE_OUTPUT);
    //hdc1080_collect();
    //hdc2010_collect();
    adc_collect();
    while (1)
    {
      rt_pin_write(D12_PIN, PIN_LOW);
      rt_thread_mdelay(Speed);
      rt_pin_write(D12_PIN, PIN_HIGH);
      rt_thread_mdelay(Speed);
    }
}


```
##四、下载程序
点击编译,并下载程序到开发板中,可以观察到开发板的D12灯不断闪烁,串口控制台不断输出ADC的有关数据

串口控制台
</div><script>                                        var loginstr = '<div class="locked">查看本帖全部内容,请<a href="javascript:;"   style="color:#e60000" class="loginf">登录</a>或者<a href="https://bbs.eeworld.com.cn/member.php?mod=register_eeworld.php&action=wechat" style="color:#e60000" target="_blank">注册</a></div>';
                                       
                                        if(parseInt(discuz_uid)==0){
                                               
                                        }                </script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script>
页: [1]
查看完整版本: 【国民技术N32WB452测评】第二期、在RT-Thread完整版中点灯及ADC的使用