本帖最后由 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
#include
#include
#define DBG_TAG "ADC"
#define DBG_LVL DBG_LOG
#include
#include
#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[5];
#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[128];
while (1)
{
ADC2ConvertedValue[1]=ADC_GetData(ADC2,ADC2_Channel_13_PB2);
ADC_Volt=(double)ADC2ConvertedValue[1]*3.267/4095;
sprintf(str,"ADC Value is %d,ADC Volt is %d.%d",ADC2ConvertedValue[1],(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
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include
#include
#include
#include
#include
/* 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的有关数据
串口控制台