zhjb1 发表于 2024-11-18 08:41

AT32F407的ADC问题

本帖最后由 zhjb1 于 2024-11-18 08:45 编辑

问题如题。AT32F407VGT7的ADC实验中的问题
一、采用官网AT32F403A_407_Firmware_Library_V2.1.4工程测试ADC,里面分别由各种ADC的实例,有几个运行后printf有输出但数值***不变——八成不对,悬空数值应该乱蹦,手触应该数值变化,但数值***稳定。
二、采用官网AT32F403_Firmware_Library_V2.1.1工程测试ADC,里面的实例与“AT32F403A_407_Firmware_Library_V2.1.4”一样,结果也一样。

三、由ATWorkbench生成的工程,其中的ADC初始化代码:
void wk_adc1_init(void){
/* add user code begin adc1_init 0 */

/* add user code end adc1_init 0 */

gpio_init_type gpio_init_struct;
adc_base_config_type adc_base_struct;

gpio_default_para_init(&gpio_init_struct);

/* add user code begin adc1_init 1 */

/* add user code end adc1_init 1 */

/*gpio--------------------------------------------------------------------*/
/* configure the IN1 pin */
gpio_init_struct.gpio_mode = GPIO_MODE_ANALOG;
gpio_init_struct.gpio_pins = ADC0_PIN;
gpio_init(ADC0_GPIO_PORT, &gpio_init_struct);

/* configure the IN2 pin */
gpio_init_struct.gpio_mode = GPIO_MODE_ANALOG;
gpio_init_struct.gpio_pins = ADC1_PIN;
gpio_init(ADC1_GPIO_PORT, &gpio_init_struct);

/* configure the IN3 pin */
gpio_init_struct.gpio_mode = GPIO_MODE_ANALOG;
gpio_init_struct.gpio_pins = ADC2_PIN;
gpio_init(ADC2_GPIO_PORT, &gpio_init_struct);

/* configure the IN6 pin */
gpio_init_struct.gpio_mode = GPIO_MODE_ANALOG;
gpio_init_struct.gpio_pins = ADC3_PIN;
gpio_init(ADC3_GPIO_PORT, &gpio_init_struct);

/* configure the IN7 pin */
gpio_init_struct.gpio_mode = GPIO_MODE_ANALOG;
gpio_init_struct.gpio_pins = ADC4_PIN;
gpio_init(ADC4_GPIO_PORT, &gpio_init_struct);

crm_adc_clock_div_set(CRM_ADC_DIV_6);

adc_tempersensor_vintrv_enable(TRUE);

/*adc_common_settings-------------------------------------------------------------*/
adc_combine_mode_select(ADC_INDEPENDENT_MODE);

/*adc_settings--------------------------------------------------------------------*/
adc_base_default_para_init(&adc_base_struct);
adc_base_struct.sequence_mode = TRUE;
adc_base_struct.repeat_mode = FALSE;//TRUE;
adc_base_struct.data_align = ADC_RIGHT_ALIGNMENT;
adc_base_struct.ordinary_channel_length = 5;
adc_base_config(ADC1, &adc_base_struct);
      //adc_resolution_set(ADC1, ADC_RESOLUTION_12B);

/* adc_ordinary_conversionmode-------------------------------------------- */
adc_ordinary_channel_set(ADC1, ADC_CHANNEL_1, 1, ADC_SAMPLETIME_1_5);
adc_ordinary_channel_set(ADC1, ADC_CHANNEL_2, 2, ADC_SAMPLETIME_1_5);
adc_ordinary_channel_set(ADC1, ADC_CHANNEL_3, 3, ADC_SAMPLETIME_1_5);
adc_ordinary_channel_set(ADC1, ADC_CHANNEL_6, 4, ADC_SAMPLETIME_1_5);
adc_ordinary_channel_set(ADC1, ADC_CHANNEL_16, 5, ADC_SAMPLETIME_1_5);

adc_ordinary_conversion_trigger_set(ADC1, ADC12_ORDINARY_TRIG_SOFTWARE, TRUE);

adc_ordinary_part_mode_enable(ADC1, FALSE);

adc_dma_mode_enable(ADC1, TRUE);
/**
   * Users need to configure ADC1 interrupt functions according to the actual application.
   * 1. Call the below function to enable the corresponding ADC1 interrupt.
   *   --adc_interrupt_enable(...)
   * 2. Add the user's interrupt handler code into the below function in the at32f403a_407_int.c file.
   *   --void ADC1_2_IRQHandler(void)
   */

adc_enable(ADC1, TRUE);
//while(adc_flag_get(ADC1, ADC_RDY_FLAG) == RESET);
/* adc calibration-------------------------------------------------------- */
adc_calibration_init(ADC1);
while(adc_calibration_init_status_get(ADC1));
adc_calibration_start(ADC1);
while(adc_calibration_status_get(ADC1));
      adc_calibration_start(ADC1);
      while(adc_calibration_status_get(ADC1));

/* add user code begin adc1_init 2 */

/* add user code end adc1_init 2 */
}

设置了ADC,通道1-3,6,7(代码里显示的是通道16-温度传感器),自己写了一个软件触发acdTest()代码:
void adcTest(void){
//int i;
/*adc_ordinary_software_trigger_enable(ADC1, TRUE);
adc_preempt_software_trigger_enable(ADC1, TRUE);
delayer(100);
if((dma_trans_complete_flag)||adc_calibration_status_get(ADC1)){//(adc1_overflow_flag != 1)){
adcx=adc_preempt_conversion_data_get(ADC1,ADC_PREEMPT_CHANNEL_1);
adcx=adc_preempt_conversion_data_get(ADC1,ADC_PREEMPT_CHANNEL_2);
adcx=adc_preempt_conversion_data_get(ADC1,ADC_PREEMPT_CHANNEL_3);
adcx=adc_preempt_conversion_data_get(ADC1,ADC_PREEMPT_CHANNEL_4);
//adcx=adc_preempt_conversion_data_get(ADC1,ADC_PREEMPT_CHANNEL_7);
}*/
adc_calibration_init(ADC1);
adc_ordinary_part_mode_enable(ADC1, TRUE);
adc_ordinary_software_trigger_enable(ADC1, TRUE);
adc_enable(ADC1, TRUE);
adc_calibration_start(ADC1);
delayer(1000);
while(adc_calibration_status_get(ADC1));
//while(dma_trans_complete_flag);
//for(i=0;i<5;i++){adcx=ADC1ConvertedValue<<16;}
adcx=adc_preempt_conversion_data_get(ADC1,ADC_PREEMPT_CHANNEL_1);
adcx=adc_preempt_conversion_data_get(ADC1,ADC_PREEMPT_CHANNEL_2);
adcx=adc_preempt_conversion_data_get(ADC1,ADC_PREEMPT_CHANNEL_3);
adcx=adc_combine_ordinary_conversion_data_get();;//adc_preempt_conversion_data_get(ADC1,ADC_PREEMPT_CHANNEL_4);
//adcx=adc_combine_ordinary_conversion_data_get();
}

代码中忽略了第5个通道数据,查看at32f403a_407_conf.c文档,里面所有的通道默认为4,结果可以扩充到最大,实验吗,出来数据再说,结果与官网的工程一样没有数据。
遍历at32f403a_407_conf.c由以下获得数据的方法:
adc_ordinary_conversion_data_get(adc_type *adc_x)
adc_combine_ordinary_conversion_data_get(void)
adc_preempt_conversion_data_get(adc_type *adc_x, adc_preempt_channel_type adc_preempt_channel)
对应这三种方法按照文头提示都不能成功获取数据,最好的结果是有一个可以获得一样的固定数值,与官工程结果一样,不是实际的结果。实际上本论坛里不下3篇以上关于ADC的文档或例程代码都试过,没有成功的。也许我的工程比较复杂,AWB生成后的结果是DMA 通道4_5,常规案例是DMA1 通道1.
码代码是无奈之举,看代码费力费神。
非常希望得到解答。
有答有会交流学习共同进步,用好国产芯片!
先谢谢了

zhjb1 发表于 2024-11-18 13:04

本帖最后由 zhjb1 于 2024-11-18 13:05 编辑

自己回复一下吧,AT的工程一直没有测试成功,包括网上老师们的,厂价的案例。一生气那来以前用MBED做好的STM32F103的工程,做了5路ADC等都没有更改任何设置,直接下载就Ok了。有时想想真是背气

呐咯密密 发表于 2024-11-19 10:04

你把STM32F103的工程直接烧到AT32F407里能正常运行啊?

zhjb1 发表于 2024-11-19 10:39

呐咯密密 发表于 2024-11-19 10:04
你把STM32F103的工程直接烧到AT32F407里能正常运行啊?

是STM32F103RBT6的芯片,打开后直接下载所有都正常,工程使用MBED实现的。

zhjb1 发表于 2024-11-19 11:03

本帖最后由 zhjb1 于 2024-11-19 11:10 编辑

今天测试的结果汇报如下:
参考了一堆代码,最后按照比较符合逻辑的重组分别放到不同位置,并且将我的5路ADC减少到4路(先测试出来再说);好的结果是目前可以采样了,四路信号都出来了:ADC1_IN1,ADC1_IN2,ADC1_IN3,ADC1_IN6,(ADC1_IN7注释掉了,并且轮询5->4).不好的结果是DMA2_4出来的数据次序乱蹦,几乎没有规律可循。顺带说一下:ADC出来的,TFTLCD不能显示了——估计是地址冲突,捡来将地址强行分开的方法学习一下,应该能解决的。
下边将代码码出来:
DMA、ADC的初始化代码基本没变,知识通道数5减到4,注释掉一个ADC定义。
中断函数at32f403a_407_int.c"的DMA4_2增加以下:
void DMA2_Channel4_5_IRQHandler(void){
uint32_t time6Base=300;
//ADC1_DMA2 IRQ
dma_interrupt_enable(DMA2_CHANNEL4, DMA_FDT_INT, TRUE);
dma_channel_enable(DMA2_CHANNEL4, TRUE);
if(dma_interrupt_flag_get(DMA2_FDT4_FLAG) != RESET){
    dma_flag_clear(DMA2_FDT4_FLAG);
    dma_trans_complete_flag++;
}
}
主程序中增加一个启动ADCTest函数:
void adcTest(uint32_t intn){
__IO uint32_t index;
index=intn;
wk_dma2_channel4_init();
dma_channel_enable(DMA2_CHANNEL4, TRUE);
//wk_adc1_init();
adc_ordinary_software_trigger_enable(ADC1, TRUE);//Software
dma_channel_enable(DMA2_CHANNEL4, TRUE);//FALSE);
dma_data_number_set(DMA2_CHANNEL4,256);
adc_ordinary_software_trigger_enable(ADC1, TRUE);//softwire trige again
delayer(100);
if((dma_trans_complete_flag)||(adc_flag_get(ADC1,ADC_VMOR_FLAG))){//adc1_complete_flag)){//adc_calibration_status_get(ADC1)){//
//index=0;intn=0;
   adcx=ADC1_Buffer;
   adcx=ADC1_Buffer;
   adcx=ADC1_Buffer;
   adcx=ADC1_Buffer;
   printf("intn=%3d ADC1=%4d ADC2=%4d ADC3=%4d ADC4=%4d \n\r",index,adcx,adcx,adcx,adcx);

}
}
说明:
原来__IO uint32_t index;是这样定义的,改成__IO uint32_t index;因为多少结果都一样;
实际的index通过一个按键函数intn赋值给index,试过已经找到的所有相关这类数组定义的方法,结果一样,要么得不到,要么只能间隔得到,要么于此结果一样;
最后用改变index的初值,index不变由按键改变,第二个括号里的数值改变,最后的结果就是index==0,第二个括号0,0,2,2。尽管看着象是固定的实际上的数值用串口输出是乱变的!
DMA的到的数据是这样的嘛?如果不是,问题在哪里?
谢谢,欢迎指导讨论。
漏说了一点:改一下代码的顺序:线DMA转换完成,再启动ADC软件触发,或反过来。目前的代码是判断两者都完成开始读取数据。
页: [1]
查看完整版本: AT32F407的ADC问题