GD32F303VET6-串口&定时器&ADC&时钟等外设的配置
GD32F303VET6系统时钟,定时器,ADC,串口
·
1.系统时钟的配置
通过用户手册时钟架构可以得到,该芯片的时钟最大频率120MHZ,APB1最大60MHZ,APB2最大120MHZ。

1.1 系统时钟代码配置:
void Clock_Init(void)
{
rcu_osci_on(RCU_HXTAL);
while(rcu_osci_stab_wait(RCU_HXTAL) == ERROR); // 等待HSE稳定
/* 2. 配置PLL */
// GD32F303VE的PLL配置公式: PLL = (HSE / PREDV0) * PLLMF
// 目标: HSE=8MHz → PLL=120MHz
// 选择PREDV0不分频(=1), PLLMF=15倍频 (8MHz * 15 = 120MHz)
rcu_predv0_config(RCU_PREDV0_DIV1); // PREDV0 = 1分频
rcu_pll_config(RCU_PLLSRC_HXTAL_IRC48M, RCU_PLL_MUL15); // PLL倍频15
/* 3. 使能PLL并等待就绪 */
rcu_osci_on(RCU_PLL_CK);
while(rcu_osci_stab_wait(RCU_PLL_CK) == ERROR);
/* 4. 配置Flash等待周期(120MHz需3个等待周期) */
fmc_wscnt_set(WS_WSCNT_2);
/* 5. 切换系统时钟源到PLL */
// rcu_system_clock_source_config(RCU_CKSYSSRC_PLL);
// while(rcu_system_clock_source_get() != RCU_CKSYSSRC_PLL);
/* 6. 配置AHB/APB分频 */
rcu_ahb_clock_config(RCU_AHB_CKSYS_DIV1); // AHB = 120MHz
rcu_apb1_clock_config(RCU_APB1_CKAHB_DIV2); // APB1 = 60MHz
rcu_apb2_clock_config(RCU_APB2_CKAHB_DIV1); // APB2 = 120MHz
systick_config();//配置系统主频120M,外部8M晶振
}
2.串口配置
void UART_Init(void)
{
/*********************UART0 PA9 PA10*********************************************/
#if 1
rcu_periph_clock_enable(RCU_USART0); //开启USART0时钟
rcu_periph_clock_enable(RCU_GPIOA); //开启GPIOA时钟
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9); //PA9(TX)配置
为复用推挽输出
gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_10); //PA10(RX)配
置为浮空输入
usart_deinit(USART0);
usart_baudrate_set(USART0, 115200);
usart_word_length_set(USART0, USART_WL_8BIT);
usart_stop_bit_set(USART0, USART_STB_1BIT);
usart_parity_config(USART0, USART_PM_NONE);
usart_hardware_flow_rts_config(USART0, USART_RTS_DISABLE);
usart_hardware_flow_cts_config(USART0, USART_CTS_DISABLE);
usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);
usart_receive_config(USART0, USART_RECEIVE_ENABLE);
nvic_irq_enable(USART0_IRQn,1,1); //设置USART0 抢占优先级:1,响应优先级:1
usart_interrupt_enable(USART0,USART_INT_RBNE); //使能读数据缓冲区非空中断和过载错误中断
//usart_interrupt_enable(USART0,USART_INT_IDLE); //使能空闲中断
usart_interrupt_flag_clear(USART0,USART_INT_FLAG_RBNE);//清除读数据缓冲区非空中断标志
usart_enable(USART0); //使能USART0
#endif
}
/* USART0 debug中断服务函数 */
uint16_t uart_rev_buf[256];
void USART0_IRQHandler(void)
{
if(usart_interrupt_flag_get(USART0,USART_INT_FLAG_RBNE))
{
// usart_data_transmit(USART0, rx_char); //将接受的数据通串口发送出去
uint8_t rx_char = usart_data_receive(USART0); // 接收单个字符
if(uart_rev_counter < 256)
{
uart_rev_buf[uart_rev_counter] = rx_char;
uart_rev_counter++;
}
usart_interrupt_flag_clear(USART0,USART_INT_FLAG_RBNE); //清除读数据缓冲区非空中断标志
}
}
3. ADC配置结合DMA
本人使用的是ADC+DMA读取数据。
如想使用ADC中断读取数据,可以去adc库函数的头文件.h中去查找相关的中断函数,开启对应的adc中断标志位;接着打开nvic中断。再去写中断服务函数即可。

void ADC_Init(void)
{
/**ADC0 初始化**/
//1:初始化ADC所用到的GPIO口
rcu_periph_clock_enable(RCU_GPIOA); //开启GPIOA时钟
gpio_init(GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, GPIO_PIN_0); //PA0(ADC0_IN0)配置为模拟输入 PA2 ADC0_IN2
gpio_init(GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, GPIO_PIN_1); //PA1(ADC0_IN1)配置为模拟输入 PA1 ADC0_IN8
//2: 使能ADC时钟和对ADC时钟进行分频
rcu_periph_clock_enable(RCU_ADC0); //开启ADC0时钟
rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV4); //ADC时钟为APB2的4分频,即30Mhz。//最大40Mhz
adc_deinit(ADC0);
adc_resolution_config(ADC0, ADC_RESOLUTION_12B); //配置ADC0分辨率为12位
/* configure the ADC sync mode */
adc_mode_config(ADC_MODE_FREE);//独立模式,
/* ADC data alignment config */
adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT); //ADC0数据右对齐
/* ADC scan mode function enable */
adc_special_function_config(ADC0, ADC_SCAN_MODE, ENABLE); //ADC0扫描模式使能
adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, DISABLE); //ADC0连续模式失能
/* ADC regular channel config */
adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, 2); //ADC0注入通道组长度为2
adc_regular_channel_config(ADC0, 0, ADC_CHANNEL_0, ADC_SAMPLETIME_7POINT5); //ADC0通道0配置为注入组序列0,采样时间1.5周期
adc_regular_channel_config(ADC0, 1, ADC_CHANNEL_1, ADC_SAMPLETIME_7POINT5); //ADC0通道1配置为注入组序列1,采样时间1.5周期
/* ADC trigger config */
adc_external_trigger_source_config(ADC0, ADC_REGULAR_CHANNEL, ADC0_1_2_EXTTRIG_REGULAR_NONE); //配置ADC0注入组软件触发
adc_external_trigger_config(ADC0, ADC_REGULAR_CHANNEL, ENABLE); //ADC0注入组外部触发使能
adc_enable(ADC0); //ADC0使能
adc_calibration_enable(ADC0); //ADC0校准复位
adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL);
adc_dma_mode_enable(ADC0);//使能ADC-DMA功能
//////////////DMA初始化////////////////////
//ADC 0
/* initialize DMA0 channel0(ADC0) */
dma_parameter_struct DMA_InitStruct;
rcu_periph_clock_enable(RCU_DMA0); //开启DMA时钟
dma_deinit(DMA0, DMA_CH0);
DMA_InitStruct.direction = DMA_PERIPHERAL_TO_MEMORY; //外设到内存
DMA_InitStruct.periph_addr = (uint32_t)(&ADC_RDATA(ADC0));
DMA_InitStruct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; //外设增量
DMA_InitStruct.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;
DMA_InitStruct.memory_addr = (uint32_t)adc1_rev_buf;
DMA_InitStruct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; //内存增量
DMA_InitStruct.memory_width = DMA_MEMORY_WIDTH_16BIT;
DMA_InitStruct.number = 2; //ADC通道数
DMA_InitStruct.priority = DMA_PRIORITY_MEDIUM;
dma_init(DMA0, DMA_CH0, &DMA_InitStruct);
dma_circulation_enable(DMA0, DMA_CH0); //循环执行
dma_channel_enable(DMA0, DMA_CH0);
dma_interrupt_enable(DMA0,DMA_CH0,DMA_INT_FTF); //开启DMA传输完成中断标志
/***开启DMA中断**/
nvic_irq_enable(DMA0_Channel0_IRQn,5,0);
}
//ADC完成回调函数
void ADC_DMATranCallBack_Hook(void (*ADCTran_CallBack)(uint16_t *data, uint16_t len))
{
ADC1Rev_CallBack = ADCTran_CallBack;
}
uint16_t adc1_rev_buf[2]; //因为adc通过我只开启2个
static void (*ADC1Rev_CallBack)(uint16_t *data, uint16_t len);
void DMA0_Channel0_IRQHandler(void)//ADC
{
if(dma_interrupt_flag_get(DMA0,DMA_CH0,DMA_INT_FLAG_FTF) != RESET)
{
if(NULL != ADC1Rev_CallBack)
{
ADC1Rev_CallBack(adc1_rev_buf,2);
}
dma_interrupt_flag_clear(DMA0,DMA_CH0,DMA_INT_FLAG_FTF); //清除传输完成标识位
}
}
/////*********在main函数初始化中调用回调函数将其注册到中断服务函数中
***************/////
/*
ADC1采样完成中断回调
*/
static void Sample1RevData(uint16_t* data, uint16_t len)
{
uint16_t i = 0;
for(i = 0 ; i < len; i++)
{
adcp.addma[i] = data[i];
printf(" ADC0value[%d] is %d \r\n",i,adcp.addma[i]);
}
}
int main()
{
systick_config(); // 初始化systick计时器
ADC_DMATranCallBack_Hook(Sample1RevData)
while(1)
{
}
}
4. 定时器 计数 以及 输出通道PWM
该芯片的高级定时器为0和7,想要输出pwm需要和其他定时器相比多一个控制输出函数
void Timer_Init(void)
{
timer_parameter_struct TIMER_StructInit;
timer_oc_parameter_struct timer_oc_parameter_struct_Init; //定义通道输出比较结构体
/***************** timer1 计数定时器*********************************/
rcu_periph_clock_enable(RCU_TIMER1);
timer_deinit(TIMER1);
TIMER_StructInit.repetitioncounter = 0;
TIMER_StructInit.clockdivision = TIMER_CKDIV_DIV1;
TIMER_StructInit.alignedmode = TIMER_COUNTER_CENTER_UP;
TIMER_StructInit.counterdirection = TIMER_COUNTER_UP;
TIMER_StructInit.period = 10000 - 1; //重装载值
TIMER_StructInit.prescaler = 12000 - 1; // 预分频器
timer_init(TIMER1, &TIMER_StructInit);
nvic_irq_enable(TIMER1_IRQn, 0, 0);
timer_interrupt_enable(TIMER1, TIMER_INT_UP);
// timer_interrupt_flag_clear(TIMER1, TIMER_INT_FLAG_UP);
timer_enable(TIMER1); //使能TIMER1,计数器开始计数
/*************** 定时器TIMER7 CH0 Pin:PC6 ******************************/
rcu_periph_clock_enable(RCU_TIMER7); //开启TIMER1时钟
rcu_periph_clock_enable(RCU_GPIOC); //开启GPIO时钟
rcu_periph_clock_enable(RCU_AF); //开启复用时钟
gpio_init(GPIOC, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6); //PA1配置为复用推挽输出
timer_deinit(TIMER7); //TIMER1复位
TIMER_StructInit.alignedmode = TIMER_COUNTER_EDGE; //对齐模式:边沿对齐模式
TIMER_StructInit.counterdirection = TIMER_COUNTER_UP; //计数模式:向上计数
TIMER_StructInit.clockdivision = TIMER_CKDIV_DIV1; //时钟分频
TIMER_StructInit.period = 1000 - 1; //自动重装载值(计数周期)
TIMER_StructInit.prescaler = 120 - 1; //预分频器值
timer_init(TIMER7, &TIMER_StructInit); //TIMER1初始化
timer_oc_parameter_struct_Init.outputstate = TIMER_CCX_ENABLE; //通道输出状态:使能
timer_oc_parameter_struct_Init.outputnstate = TIMER_CCXN_DISABLE; // 禁用互补通道输出
timer_oc_parameter_struct_Init.ocpolarity = TIMER_OC_POLARITY_HIGH; //通道输出极性:高电平为有效电平
timer_channel_output_config(TIMER7, TIMER_CH_0, &timer_oc_parameter_struct_Init);//初始化通道输出比较模式
timer_channel_output_shadow_config(TIMER7, TIMER_CH_0, TIMER_OC_SHADOW_DISABLE); //开启TIMER1通道输出影子功能
timer_channel_output_mode_config(TIMER7, TIMER_CH_0, TIMER_OC_MODE_PWM0); //通道输出比较模式:PWM0模式
timer_channel_output_pulse_value_config(TIMER7, TIMER_CH_0, 500); //设置输出比较值 占空比50%
/* TIMER7 primary output function enable 高级定时器(0和7)特有*/
timer_primary_output_config(TIMER7,ENABLE);
timer_enable(TIMER7); //使能TIMER1,计数器开始计数
/***************** 定时器TIMER0 CH0 Pin:PA8 *****************************/
rcu_periph_clock_enable(RCU_GPIOA);
/*Configure PA8(TIMER0_CH0) as alternate function*/
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_8);
rcu_periph_clock_enable(RCU_TIMER0);
timer_deinit(TIMER0);
/* TIMER0 configuration */
TIMER_StructInit.prescaler = 120-1;
TIMER_StructInit.alignedmode = TIMER_COUNTER_EDGE;
TIMER_StructInit.counterdirection = TIMER_COUNTER_UP;
TIMER_StructInit.period = 500;
TIMER_StructInit.clockdivision = TIMER_CKDIV_DIV1;
TIMER_StructInit.repetitioncounter = 0;
timer_init(TIMER0,&TIMER_StructInit);
/* CH0 configuration in PWM mode */
timer_oc_parameter_struct_Init.outputstate = TIMER_CCX_ENABLE;
timer_oc_parameter_struct_Init.outputnstate = TIMER_CCXN_DISABLE;
timer_oc_parameter_struct_Init.ocpolarity = TIMER_OC_POLARITY_HIGH;
timer_oc_parameter_struct_Init.ocnpolarity = TIMER_OCN_POLARITY_HIGH;
timer_oc_parameter_struct_Init.ocidlestate = TIMER_OC_IDLE_STATE_LOW;
timer_oc_parameter_struct_Init.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;
timer_channel_output_config(TIMER0,TIMER_CH_0,&timer_oc_parameter_struct_Init);
timer_channel_output_mode_config(TIMER0,TIMER_CH_0,TIMER_OC_MODE_PWM0);
timer_channel_output_shadow_config(TIMER0,TIMER_CH_0,TIMER_OC_SHADOW_DISABLE);
timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_0,250);
/* TIMER7 primary output function enable 高级定时器(0和7)特有*/
timer_primary_output_config(TIMER0,ENABLE);
/* auto-reload preload enable */
timer_auto_reload_shadow_enable(TIMER0);
timer_enable(TIMER0);
更多推荐



所有评论(0)