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);
	
	

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐