一、选开发库
从芯片角度看,硬件上是PIN2PIN的,GD32F130外设地址设计是参考STM32F030,但STM32F030是M0内核,GD32F130是M3内核,时钟也可以到72M,多了APB2总线等。所以考虑用STM32F030的库来改写,本次实验采用的是STM32F0xx_DFP.1.5.0版本。
二、使用步骤
1.安装pack包和配置
从GD官网下载编译器芯片支持包:GigaDevice.GD32F1x0_DFP.3.2.0.pack
然后找一个原先用STM32f030做过的项目模板,配置一下编译环境。
Device选项里选择GD的对应的具体芯片,本次用的是130C8系列,效果图如下:
工程架构如下,继续采用ST的系统,如下
启动文件startup_stm32f0xx.s可以不用修改,直接使用。
系统文件system_stm32f0xx.c可以简单修改,主要是SetSysClock()函数,
主频提高到72MHz,
CC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLMULL6 )
改为
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLMULL9 )
另外增加APB2 配置,
/* PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
后面发现以上几项参数不修改也可以直接使用。
2.项目编译和功能debug
现在直接编译后下载到芯片,发现GPIO,串口,PWM, 软件I2C(为代码通用性一些低速的通讯都采用软件模拟方式)等功能都能正常使用了。但ADC无法工作,表现为程序卡住,后debug发现是查询ADC转换是否完成始终没返回,
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
后需仔细核对后,发现虽然GD32F130的ADC内存地址段(0x40012400-0x400127ff)和STM32F030是一致的,但各个具体寄存器定义的状态和标志位还是不一样的,例如ADC_FLAG_EOC,ADCx->DR,ADC_CHANNEL定义都不一致。甚至宏定义ADC_BASE都不一样,在STM库里要用ADC1_BASE这个宏,前面这么顺利,这个地方轻敌了,debug了很久,被坑了一把…
最后参考了GD32F130的官方库中ADC内容,抽取出部分必要的内容,导入到现项目中,终于把ADC功能模块搞定。
具体参考代码如下
头文件增加内容
//
//for GD130
#define gdREG32(addr) (*(volatile uint32_t *)(uint32_t)(addr))
#define gdBIT(x) ((uint32_t)((uint32_t)0x01U<<(x)))
#define gdBITS(start, end) ((0xFFFFFFFFUL << (start)) & (0xFFFFFFFFUL >> (31U - (uint32_t)(end))))
#define gdADC_STAT gdREG32(0x40012400U)
#define gdADC_CTL1 gdREG32(0x40012408U)
#define gdADC_RDATA gdREG32(0x4001244CU)
#define gdADC_RSQ0 gdREG32(0x4001242CU)
#define gdADC_RSQ1 gdREG32(0x40012430U)
#define gdADC_RSQ2 gdREG32(0x40012434U)
#define gdADC_SAMPT0 gdREG32(0x4001240CU)
#define gdADC_SAMPT1 gdREG32(0x40012410U)
#define gdADC_CTL1_ADCON gdBIT(0)
#define gdADC_CTL1_CLB gdBIT(2)
#define gdADC_CTL1_RSTCLB gdBIT(3)
#define gdADC_CTL1_SWRCST gdBIT(22)
#define gdADC_FLAG_EOC gdBIT(1)
/* gd_ADC channel definitions */
#define gdADC_CHANNEL_0 ((uint8_t)0x00U)
#define gdADC_CHANNEL_1 ((uint8_t)0x01U)
#define gdADC_CHANNEL_2 ((uint8_t)0x02U)
#define gdADC_CHANNEL_3 ((uint8_t)0x03U)
#define gdADC_CHANNEL_4 ((uint8_t)0x04U)
#define gdADC_CHANNEL_5 ((uint8_t)0x05U)
#define gdADC_CHANNEL_6 ((uint8_t)0x06U)
#define gdADC_CHANNEL_7 ((uint8_t)0x07U)
#define gdADC_CHANNEL_8 ((uint8_t)0x08U)
#define gdADC_CHANNEL_9 ((uint8_t)0x09U)
#define gdADC_CHANNEL_10 ((uint8_t)0x0AU)
#define gdADC_CHANNEL_11 ((uint8_t)0x0BU)
#define gdADC_CHANNEL_12 ((uint8_t)0x0CU)
#define gdADC_CHANNEL_13 ((uint8_t)0x0DU)
#define gdADC_CHANNEL_14 ((uint8_t)0x0EU)
#define gdADC_CHANNEL_15 ((uint8_t)0x0FU)
#define gdADC_CHANNEL_16 ((uint8_t)0x10U)
#define gdADC_CHANNEL_17 ((uint8_t)0x11U)
#define gdADC_CHANNEL_18 ((uint8_t)0x12U)
/* adc_samptx register value */
#define gdSAMPTX_SPT(regval) (gdBITS(0,2) & ((uint32_t)(regval) << 0))
#define gdADC_SAMPLETIME_1POINT5 gdSAMPTX_SPT(0)
#define gdADC_SAMPLETIME_7POINT5 gdSAMPTX_SPT(1)
#define gdADC_SAMPLETIME_13POINT5 gdSAMPTX_SPT(2)
#define gdADC_SAMPLETIME_28POINT5 gdSAMPTX_SPT(3)
#define gdADC_SAMPLETIME_41POINT5 gdSAMPTX_SPT(4)
#define gdADC_SAMPLETIME_55POINT5 gdSAMPTX_SPT(5)
#define gdADC_SAMPLETIME_71POINT5 gdSAMPTX_SPT(6)
#define gdADC_SAMPLETIME_239POINT5 gdSAMPTX_SPT(7)
#define gdADC_RSQX_RSQN gdBITS(0,4)
#define gdADC_RSQ0_RL gdBITS(20,23)
#define gdADC_SAMPTX_SPTN gdBITS(0,2)
///
...
void gdADC_Init(void);
u16 gdGet_Adc(uint8_t ch);
在源文件中添加,
void gdadc_enable(void)
{
if(RESET == (gdADC_CTL1 & gdADC_CTL1_ADCON)){
gdADC_CTL1 |= (uint32_t)gdADC_CTL1_ADCON;
}
}
void gdadc_disable(void)
{
gdADC_CTL1 &= ~((uint32_t)gdADC_CTL1_ADCON);
}
void gdADC_StartOfConversion()
{
gdADC_CTL1 |= gdADC_CTL1_SWRCST;
}
uint16_t gdADC_GetConversionValue()
{
return ((uint16_t)gdADC_RDATA);
}
void gdadc_flag_clear(uint32_t flag)
{
gdADC_STAT &= ~((uint32_t)flag);
}
void gdadc_calibration_enable(void)
{
gdADC_CTL1 |= (uint32_t) gdADC_CTL1_RSTCLB;
while((gdADC_CTL1 & gdADC_CTL1_RSTCLB)){
}
gdADC_CTL1 |= gdADC_CTL1_CLB;
while((gdADC_CTL1 & gdADC_CTL1_CLB)){
}
}
void gdadc_regular_channel_config(uint8_t channel, uint32_t sample_time)
{
uint32_t rsq,sampt;
#ifdef GD32F130_150
if(gdADC_CHANNEL_18 == channel){
channel = gdADC_CHANNEL_0;
}
#endif
rsq = gdADC_RSQ2;
rsq &= ~((uint32_t)gdADC_RSQX_RSQN);
rsq |= ((uint32_t)channel );
gdADC_RSQ2 = rsq;
if(channel < 10U){
sampt = gdADC_SAMPT1;
sampt &= ~((uint32_t)(gdADC_SAMPTX_SPTN << (3U*channel)));
sampt |= (uint32_t)(sample_time << (3U*channel));
gdADC_SAMPT1 = sampt;
}else if(channel < 18U){
sampt = gdADC_SAMPT0;
sampt &= ~((uint32_t)(gdADC_SAMPTX_SPTN << (3U*(channel-10U))));
sampt |= (uint32_t)(sample_time << (3U*(channel-10U)));
gdADC_SAMPT0 = sampt;
}else{
}
}
void gdADC_Init(void)
{
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_ADCCLKConfig(RCC_ADCCLK_PCLK_Div4);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE );
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0 | GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);
ADC_DeInit(ADC1);
ADC_StructInit(&ADC_InitStructure);
//ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; //not support
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Upward;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_Cmd(ADC1, ENABLE);
//gdadc_enable(); //OK also
delay_ms(1);
gdadc_calibration_enable();
}
u16 gdGet_Adc(uint8_t ch)
{
u16 ValResult=0;
gdadc_regular_channel_config(ch,gdADC_SAMPLETIME_55POINT5);
gdADC_StartOfConversion();
gdADC_StartOfConversion(); //a bug here related to trigger config above
while(!ADC_GetFlagStatus(ADC1, gdADC_FLAG_EOC));
ValResult = gdADC_GetConversionValue();
gdadc_flag_clear(gdADC_FLAG_EOC);
return ValResult;
}
在main()中ADC测试OK
....
gdADC_Init();
while(1)
{
delay_ms(1000);
adc_value = gdGet_Adc(gdADC_CHANNEL_0);
printf("ADC0= %drn", adc_value);
}
一、选开发库
从芯片角度看,硬件上是PIN2PIN的,GD32F130外设地址设计是参考STM32F030,但STM32F030是M0内核,GD32F130是M3内核,时钟也可以到72M,多了APB2总线等。所以考虑用STM32F030的库来改写,本次实验采用的是STM32F0xx_DFP.1.5.0版本。
二、使用步骤
1.安装pack包和配置
从GD官网下载编译器芯片支持包:GigaDevice.GD32F1x0_DFP.3.2.0.pack
然后找一个原先用STM32f030做过的项目模板,配置一下编译环境。
Device选项里选择GD的对应的具体芯片,本次用的是130C8系列,效果图如下:
工程架构如下,继续采用ST的系统,如下
启动文件startup_stm32f0xx.s可以不用修改,直接使用。
系统文件system_stm32f0xx.c可以简单修改,主要是SetSysClock()函数,
主频提高到72MHz,
CC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLMULL6 )
改为
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLMULL9 )
另外增加APB2 配置,
/* PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
后面发现以上几项参数不修改也可以直接使用。
2.项目编译和功能debug
现在直接编译后下载到芯片,发现GPIO,串口,PWM, 软件I2C(为代码通用性一些低速的通讯都采用软件模拟方式)等功能都能正常使用了。但ADC无法工作,表现为程序卡住,后debug发现是查询ADC转换是否完成始终没返回,
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
后需仔细核对后,发现虽然GD32F130的ADC内存地址段(0x40012400-0x400127ff)和STM32F030是一致的,但各个具体寄存器定义的状态和标志位还是不一样的,例如ADC_FLAG_EOC,ADCx->DR,ADC_CHANNEL定义都不一致。甚至宏定义ADC_BASE都不一样,在STM库里要用ADC1_BASE这个宏,前面这么顺利,这个地方轻敌了,debug了很久,被坑了一把…
最后参考了GD32F130的官方库中ADC内容,抽取出部分必要的内容,导入到现项目中,终于把ADC功能模块搞定。
具体参考代码如下
头文件增加内容
//
//for GD130
#define gdREG32(addr) (*(volatile uint32_t *)(uint32_t)(addr))
#define gdBIT(x) ((uint32_t)((uint32_t)0x01U<<(x)))
#define gdBITS(start, end) ((0xFFFFFFFFUL << (start)) & (0xFFFFFFFFUL >> (31U - (uint32_t)(end))))
#define gdADC_STAT gdREG32(0x40012400U)
#define gdADC_CTL1 gdREG32(0x40012408U)
#define gdADC_RDATA gdREG32(0x4001244CU)
#define gdADC_RSQ0 gdREG32(0x4001242CU)
#define gdADC_RSQ1 gdREG32(0x40012430U)
#define gdADC_RSQ2 gdREG32(0x40012434U)
#define gdADC_SAMPT0 gdREG32(0x4001240CU)
#define gdADC_SAMPT1 gdREG32(0x40012410U)
#define gdADC_CTL1_ADCON gdBIT(0)
#define gdADC_CTL1_CLB gdBIT(2)
#define gdADC_CTL1_RSTCLB gdBIT(3)
#define gdADC_CTL1_SWRCST gdBIT(22)
#define gdADC_FLAG_EOC gdBIT(1)
/* gd_ADC channel definitions */
#define gdADC_CHANNEL_0 ((uint8_t)0x00U)
#define gdADC_CHANNEL_1 ((uint8_t)0x01U)
#define gdADC_CHANNEL_2 ((uint8_t)0x02U)
#define gdADC_CHANNEL_3 ((uint8_t)0x03U)
#define gdADC_CHANNEL_4 ((uint8_t)0x04U)
#define gdADC_CHANNEL_5 ((uint8_t)0x05U)
#define gdADC_CHANNEL_6 ((uint8_t)0x06U)
#define gdADC_CHANNEL_7 ((uint8_t)0x07U)
#define gdADC_CHANNEL_8 ((uint8_t)0x08U)
#define gdADC_CHANNEL_9 ((uint8_t)0x09U)
#define gdADC_CHANNEL_10 ((uint8_t)0x0AU)
#define gdADC_CHANNEL_11 ((uint8_t)0x0BU)
#define gdADC_CHANNEL_12 ((uint8_t)0x0CU)
#define gdADC_CHANNEL_13 ((uint8_t)0x0DU)
#define gdADC_CHANNEL_14 ((uint8_t)0x0EU)
#define gdADC_CHANNEL_15 ((uint8_t)0x0FU)
#define gdADC_CHANNEL_16 ((uint8_t)0x10U)
#define gdADC_CHANNEL_17 ((uint8_t)0x11U)
#define gdADC_CHANNEL_18 ((uint8_t)0x12U)
/* adc_samptx register value */
#define gdSAMPTX_SPT(regval) (gdBITS(0,2) & ((uint32_t)(regval) << 0))
#define gdADC_SAMPLETIME_1POINT5 gdSAMPTX_SPT(0)
#define gdADC_SAMPLETIME_7POINT5 gdSAMPTX_SPT(1)
#define gdADC_SAMPLETIME_13POINT5 gdSAMPTX_SPT(2)
#define gdADC_SAMPLETIME_28POINT5 gdSAMPTX_SPT(3)
#define gdADC_SAMPLETIME_41POINT5 gdSAMPTX_SPT(4)
#define gdADC_SAMPLETIME_55POINT5 gdSAMPTX_SPT(5)
#define gdADC_SAMPLETIME_71POINT5 gdSAMPTX_SPT(6)
#define gdADC_SAMPLETIME_239POINT5 gdSAMPTX_SPT(7)
#define gdADC_RSQX_RSQN gdBITS(0,4)
#define gdADC_RSQ0_RL gdBITS(20,23)
#define gdADC_SAMPTX_SPTN gdBITS(0,2)
///
...
void gdADC_Init(void);
u16 gdGet_Adc(uint8_t ch);
在源文件中添加,
void gdadc_enable(void)
{
if(RESET == (gdADC_CTL1 & gdADC_CTL1_ADCON)){
gdADC_CTL1 |= (uint32_t)gdADC_CTL1_ADCON;
}
}
void gdadc_disable(void)
{
gdADC_CTL1 &= ~((uint32_t)gdADC_CTL1_ADCON);
}
void gdADC_StartOfConversion()
{
gdADC_CTL1 |= gdADC_CTL1_SWRCST;
}
uint16_t gdADC_GetConversionValue()
{
return ((uint16_t)gdADC_RDATA);
}
void gdadc_flag_clear(uint32_t flag)
{
gdADC_STAT &= ~((uint32_t)flag);
}
void gdadc_calibration_enable(void)
{
gdADC_CTL1 |= (uint32_t) gdADC_CTL1_RSTCLB;
while((gdADC_CTL1 & gdADC_CTL1_RSTCLB)){
}
gdADC_CTL1 |= gdADC_CTL1_CLB;
while((gdADC_CTL1 & gdADC_CTL1_CLB)){
}
}
void gdadc_regular_channel_config(uint8_t channel, uint32_t sample_time)
{
uint32_t rsq,sampt;
#ifdef GD32F130_150
if(gdADC_CHANNEL_18 == channel){
channel = gdADC_CHANNEL_0;
}
#endif
rsq = gdADC_RSQ2;
rsq &= ~((uint32_t)gdADC_RSQX_RSQN);
rsq |= ((uint32_t)channel );
gdADC_RSQ2 = rsq;
if(channel < 10U){
sampt = gdADC_SAMPT1;
sampt &= ~((uint32_t)(gdADC_SAMPTX_SPTN << (3U*channel)));
sampt |= (uint32_t)(sample_time << (3U*channel));
gdADC_SAMPT1 = sampt;
}else if(channel < 18U){
sampt = gdADC_SAMPT0;
sampt &= ~((uint32_t)(gdADC_SAMPTX_SPTN << (3U*(channel-10U))));
sampt |= (uint32_t)(sample_time << (3U*(channel-10U)));
gdADC_SAMPT0 = sampt;
}else{
}
}
void gdADC_Init(void)
{
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_ADCCLKConfig(RCC_ADCCLK_PCLK_Div4);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE );
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0 | GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);
ADC_DeInit(ADC1);
ADC_StructInit(&ADC_InitStructure);
//ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; //not support
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Upward;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_Cmd(ADC1, ENABLE);
//gdadc_enable(); //OK also
delay_ms(1);
gdadc_calibration_enable();
}
u16 gdGet_Adc(uint8_t ch)
{
u16 ValResult=0;
gdadc_regular_channel_config(ch,gdADC_SAMPLETIME_55POINT5);
gdADC_StartOfConversion();
gdADC_StartOfConversion(); //a bug here related to trigger config above
while(!ADC_GetFlagStatus(ADC1, gdADC_FLAG_EOC));
ValResult = gdADC_GetConversionValue();
gdadc_flag_clear(gdADC_FLAG_EOC);
return ValResult;
}
在main()中ADC测试OK
....
gdADC_Init();
while(1)
{
delay_ms(1000);
adc_value = gdGet_Adc(gdADC_CHANNEL_0);
printf("ADC0= %drn", adc_value);
}
举报