但是本实验出现了一个异常,单片机大概路出现更新事件没有启动ADC转换,可是没有找到处理办法,但是定时器的是正常工作LED灯闪烁
1.使能各种时钟和adc时钟分频输入#include "gd32f10x.h"
#include "stdio.h"
#include "bsp_adc.h"
#include "systick.h"
#include "gd32f103c_sys.h"
#define LED0 PBout(13)
#define LED1 PBout(14)
#define LED2 PBout(15)
#define LED3 PAout(8)
/*保存ADC值*/
uint32_t adc_value[4];
/*dma传输结束*/
uint32_t dma_finish;
// 使能各种时钟和adc时钟分频输入
void rcu_config_adc(void)
{
/*使能GPIO时钟 */
rcu_periph_clock_enable(RCU_GPIOA);
/* 使能ADC时钟*/
rcu_periph_clock_enable(RCU_ADC0);
rcu_periph_clock_enable(RCU_ADC1);
/* enable DMA0 clock ADC 对应的DMA 就是DMA0*/
rcu_periph_clock_enable(RCU_DMA0);
/* 配置ADC时钟 ,ADC最大14MHz*/
rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV8);
}
2.配置gpio
/*
配置gpio
*/
void gpio_config_adc(void)
{
/*配置gpio为模拟输入模式 */
gpio_init(GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, GPIO_PIN_2|GPIO_PIN_3);
}
3.配置dma
/*!
dma配置
*/
void dma_config(void)
{
/* ADC_DMA_channel configuration */
dma_parameter_struct dma_data_parameter;
/* 复位dma 通道0 */
dma_deinit(DMA0, DMA_CH0);
/* initialize DMA data mode */
dma_data_parameter.periph_addr = (uint32_t)(&ADC_RDATA(ADC0));//配置外设寄存器为adc的规则数据寄存器
dma_data_parameter.periph_inc = DMA_PERIPH_INCREASE_DISABLE;//外设寄存器地址不增加
dma_data_parameter.memory_addr = (uint32_t)(&adc_value);//存放数据的内存地址
dma_data_parameter.memory_inc = DMA_MEMORY_INCREASE_ENABLE;//存放数据的内存地址自增
dma_data_parameter.periph_width = DMA_PERIPHERAL_WIDTH_32BIT;//外设数据宽度32位 adc1[16-31]adc0[0-15]
dma_data_parameter.memory_width = DMA_MEMORY_WIDTH_32BIT; //内存数据宽度32位
dma_data_parameter.direction = DMA_PERIPHERAL_TO_MEMORY;//数据传输方式是外设到内存
dma_data_parameter.number = 2;//dma传输数量
dma_data_parameter.priority = DMA_PRIORITY_HIGH;//dma优先级高
dma_init(DMA0, DMA_CH0, &dma_data_parameter);
//循环模式开启
dma_circulation_enable(DMA0, DMA_CH0);
//中断管理器开启通道4中断
nvic_irq_enable(DMA0_Channel0_IRQn, 0, 1);
/* dam 转换结束产生中断*/
dma_interrupt_enable(DMA0, DMA_CH0, DMA_INT_FTF);
/* 使能dma通道0*/
dma_channel_enable(DMA0, DMA_CH0);
}
4.实现dma中断服务函数
/*
dma中断处理函数
*/
void DMA0_Channel0_IRQHandler(void)
{
if(dma_interrupt_flag_get(DMA0, DMA_CH0, DMA_INT_FLAG_FTF)){
//清除dma中断标记
dma_interrupt_flag_clear(DMA0, DMA_CH0, DMA_INT_FLAG_G);
dma_finish = SET;
}
}
5.定时器的配置
使用定时器TIM2的更新中断事件触发ADC采集一次,1S产生一次事件
/*!
定时器配置
*/
void timer_config(void)
{
timer_oc_parameter_struct timer_ocintpara;
timer_parameter_struct timer_initpara;
//使能定时器时钟
rcu_periph_clock_enable(RCU_TIMER2);
/* TIMER1 基本配置 */
timer_initpara.prescaler = 10800-1;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 1000-1;
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_initpara.repetitioncounter = 0;
timer_init(TIMER2,&timer_initpara);
timer_master_output_trigger_source_select(TIMER2,TIMER_TRI_OUT_SRC_UPDATE);
//更新事件产生使能位
timer_update_source_config(TIMER2,TIMER_UPDATE_SRC_GLOBAL);
timer_update_event_enable(TIMER2);
//timer_autoreload_value_config(TIMER2,1000-1);
//timer_auto_reload_shadow_enable(TIMER2);
timer_master_slave_mode_config(TIMER2,TIMER_MASTER_SLAVE_MODE_ENABLE);
timer_interrupt_flag_clear(TIMER2, TIMER_INT_FLAG_UP);//清除更新中断标记
timer_interrupt_enable(TIMER2, TIMER_INT_UP);//中断更新中断使能
nvic_irq_enable(TIMER2_IRQn, 1, 1);//使能中断并设置优先级
}
6.定时器中断服务函数
该函数主要观察定时器溢出
/*
中断服务函数
*/
void TIMER2_IRQHandler(void)
{
if(SET == timer_interrupt_flag_get(TIMER2, TIMER_INT_FLAG_UP)){
/* 清除更新中断标志 */
timer_interrupt_flag_clear(TIMER2, TIMER_INT_FLAG_UP);
LED1=!LED1;
}
}
7.adc配置函数
将adc配置为TIM2的更新事件作为触发源
void adc_config(void)
{
/* reset ADC */
adc_deinit(ADC0);
adc_deinit(ADC1);
/* ADC mode config 工作在规则并行模式 */
adc_mode_config(ADC_MODE_FREE);
/* ADC continous function enable */
adc_special_function_config(ADC0, ADC_SCAN_MODE, ENABLE);
//adc_special_function_config(ADC1, ADC_SCAN_MODE, ENABLE);
/* 右对齐*/
adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);
//adc_data_alignment_config(ADC1, ADC_DATAALIGN_RIGHT);
/* 配置规则通道数量 */
adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, 2);
// adc_channel_length_config(ADC1, ADC_REGULAR_CHANNEL, 2);
/* ADC规则模式配置;2个adc并行模式下,不可以2个adc同时采集一个通道,adc1数据放在高16位,adc0数据放在低16位*/
adc_regular_channel_config(ADC0, 0, ADC_CHANNEL_2, ADC_SAMPLETIME_55POINT5);
adc_regular_channel_config(ADC0, 1, ADC_CHANNEL_3, ADC_SAMPLETIME_55POINT5);
// adc_regular_channel_config(ADC1, 0, ADC_CHANNEL_3, ADC_SAMPLETIME_55POINT5);
//adc_regular_channel_config(ADC1, 1, ADC_CHANNEL_2, ADC_SAMPLETIME_55POINT5);
/* adc 使用TIM1 的CH1 的上升沿触发*/
adc_external_trigger_source_config(ADC0, ADC_REGULAR_CHANNEL, ADC0_1_EXTTRIG_REGULAR_T2_TRGO);
/*软件出发*/
//adc_external_trigger_source_config(ADC1, ADC_REGULAR_CHANNEL, ADC0_1_EXTTRIG_REGULAR_T2_TRGO);
/* adc触发使能*/
adc_external_trigger_config(ADC0, ADC_REGULAR_CHANNEL, ENABLE);
// adc_external_trigger_config(ADC1, ADC_REGULAR_CHANNEL, ENABLE);
/* 使能定时器*/
adc_enable(ADC0);
delay_1ms(1U);
/* 标定复位ADC */
adc_calibration_enable(ADC0);
/* 使能定时器*/
// adc_enable(ADC1);
// delay_1ms(1U);
// /* 标定复位ADC */
// adc_calibration_enable(ADC1);
/* ADC DMA 使能*/
adc_dma_mode_enable(ADC0);
}
8.测试函数
void adc_test()
{
/* 时钟初始化 */
rcu_config_adc();
/* GPIO 配置 */
gpio_config_adc();
/* TIMER 配置 */
timer_config();
/* DMA 配置 */
dma_config();
/* ADC 配置 */
adc_config();
/* 使能 TIMER1 */
timer_config();
timer_enable(TIMER2);
timer_enable(TIMER2);
timer_enable(TIMER2);
uint16_t *pdata =(uint16_t *)adc_value;
while(1)
{
delay_1ms(5);
if(dma_finish)
{
dma_finish=0;
printf("%d %d %d %d \r\n",pdata[0],pdata[1],pdata[2],pdata[3]);
}
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)