[RISC-V MCU 应用开发] 第九十章、CH32V103应用教程——ADC-DMA-TIM3触发ADC转换

[复制链接]
 楼主| RISCVLAR 发表于 2021-4-28 14:33 | 显示全部楼层 |阅读模式
本帖最后由 RISCVLAR 于 2021-4-28 14:33 编辑

CH32V103应用教程——ADC-DMA-TIM3触发ADC转换

本章教程主要在第三十章教程基础上进行,通过定时器3的TRGO事件触发启动ADC转换。

1、ADC简介及相关函数介绍
关于FLASH编程,本次所用库函数中具体函数如下:
ADC转换的启动事件可以由外部事件触发。如果设置了ADC_CTLR2寄存器的REXTTRI或IEXTTRIG位,则可分别通过外部事件触发规则组或注入组通道的转换。此时,REXTSEL[2:0]和IEXTSEL[2:0]位的配置决定规则组和注入组的外部事件源。
本章教程主要通过定时器3的TRGO事件触发启动ADC转换。关于ADC介绍,在前面章节已介绍,在此不再赘述。关于ADC具体信息,可参考CH32V103应用手册。

2、硬件设计
本章教程通过ADC1通道1~5读取开发板3.3V引脚和GND引脚ADC值,并通过串口调试助手打印显示出来。其中ADC1通道1~5对应PA1~5引脚,在进行使用测试时只需用杜邦线将PA1~5引脚与3.3V 引脚和GND引脚一一连接即可。

3软件设计
本章主要使用定时器触发ADC转换,在ADC多通道DMA读取方式基础上进行,可参考前面相关章节。具体如下:
adc.h文件
  1. #ifndef __ADC_H
  2. #define __ADC_H

  3. #include "ch32v10x_conf.h"

  4. #define  length  5

  5. void adc_Init(void);

  6. void DMA_Tx_Init(void);

  7. void ADC_DMA_CONF(void);

  8. #endif
adc.h文件主要进行相关定义和函数声明;
adc.c文件
  1. #include "adc.h"
  2. #include "debug.h"

  3. u16 ADC_ConvertedValue[length]={0,0,0};

  4. void DMA1_Channel1_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));

  5. //ADC对应GPIO初始化配置以及ADC初始化配置
  6. void adc_Init(void)
  7. {
  8.     GPIO_InitTypeDef GPIO_InitStructure;
  9.     ADC_InitTypeDef  ADC_InitStructure;

  10.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1 , ENABLE );          //使能GPIOA时钟和ADC

  11.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5; //PA1~5对应ADC通道1~5
  12.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;                                         //GPIO模式为模拟输入
  13.     GPIO_Init(GPIOA, &GPIO_InitStructure);

  14.     RCC_ADCCLKConfig(RCC_PCLK2_Div6);                                                     //设置ADC时钟分频为6分频

  15.     ADC_DeInit(ADC1);
  16.     ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;                                    //配置ADC为独立模式
  17.     ADC_InitStructure.ADC_ScanConvMode = ENABLE;                                          //多通道模式下开启扫描模式
  18.     ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;                                    //设置开启连续转换模式
  19.     ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T3_TRGO;                //定时器3外部触发
  20.     ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;                                //设置ADC数据右对齐
  21.     ADC_InitStructure.ADC_NbrOfChannel = length;                                          //规则转换的ADC通道的数目
  22.     ADC_Init(ADC1, &ADC_InitStructure);                                                   //根据ADC_InitStructure中指定的参数初始化ADC1寄存器

  23.     ADC_Cmd(ADC1, ENABLE);                       //使能ADC1

  24.     ADC_ExternalTrigConvCmd(ADC1, ENABLE);       //设置外部触发模式使能

  25.     ADC_ResetCalibration(ADC1);                  //重置ADC1校准寄存器。

  26.     while(ADC_GetResetCalibrationStatus(ADC1));  //等待复位校准结束

  27.     ADC_StartCalibration(ADC1);                  //开启AD校准

  28.     while(ADC_GetCalibrationStatus(ADC1));       //等待校准结束
  29. }

  30. //ADC DMA模式配置
  31. void DMA_Tx_Init( void )
  32. {
  33.     DMA_InitTypeDef  DMA_InitStructure;
  34.     NVIC_InitTypeDef NVIC_InitStructure;

  35.     RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1, ENABLE ); //使能开启DMA时钟

  36.     DMA_DeInit(DMA1_Channel1); //复位DMA控制器

  37.     DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&ADC1->RDATAR;  //配置外设地址为ADC数据寄存器地址
  38.     DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADC_ConvertedValue; //配置存储器地址为读取ADC值地址
  39.     DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;              //配置数据源为外设,即DMA传输方式为外设到存储器
  40.     DMA_InitStructure.DMA_BufferSize = length;                      //设置DMA数据缓冲区大小,此处设置为length
  41.     DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//设置DMA外设递增模式关闭
  42.     DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;         //设置DMA存储器递增模式开启
  43.     DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //设置外设数据大小为半字,即两个字节
  44.     DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;         //设置存储器数据大小为半字,即两个字节
  45.     DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;     //设置DMA模式为循环传输模式
  46.     DMA_InitStructure.DMA_Priority = DMA_Priority_High; //设置DMA传输通道优先级为高,当使用一 DMA通道时,优先级设置不影响
  47.     DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;        //因为此DMA传输方式为外设到存储器,因此禁用存储器到存储器传输方式
  48.     DMA_Init( DMA1_Channel1, &DMA_InitStructure );      //初始化DMA

  49.     DMA_ITConfig(DMA1_Channel1,DMA_IT_TC, ENABLE);      //使能传输完成中断

  50.     NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
  51.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  52.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  53.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  54.     NVIC_Init(&NVIC_InitStructure);

  55.     DMA_Cmd(DMA1_Channel1 , ENABLE);  //使能DMA
  56. }

  57. void ADC_DMA_CONF(void)
  58. {
  59.     adc_Init();

  60.     DMA_Tx_Init();

  61.     // 配置 ADC 通道转换顺序为1,第一个转换,采样时间为55.5个时钟周期
  62.     ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_55Cycles5);
  63.     ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 2, ADC_SampleTime_55Cycles5);
  64.     ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 3, ADC_SampleTime_55Cycles5);
  65.     ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 4, ADC_SampleTime_55Cycles5);
  66.     ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 5, ADC_SampleTime_55Cycles5);

  67.     // 使能ADC DMA 请求
  68.     ADC_DMACmd(ADC1, ENABLE);
  69. }


  70. //中断处理函数
  71. void  DMA1_Channel1_IRQHandler(void)
  72. {
  73.     printf("\r\nEnter DMA interrupt\r\n");
  74.     if(DMA_GetITStatus(DMA1_IT_TC1)!=RESET)
  75.     {
  76.         //中断处理代码
  77.         printf("\r\n The current ADCH1 value = %d \r\n", ADC_ConvertedValue[0]);
  78.         printf("\r\n The current ADCH2 value = %d \r\n", ADC_ConvertedValue[1]);
  79.         printf("\r\n The current ADCH3 value = %d \r\n", ADC_ConvertedValue[2]);
  80.         printf("\r\n The current ADCH4 value = %d \r\n", ADC_ConvertedValue[3]);
  81.         printf("\r\n The current ADCH5 value = %d \r\n", ADC_ConvertedValue[4]);
  82.         Delay_Ms(500);
  83.         DMA_ClearITPendingBit(DMA1_IT_TC1);
  84.     }
  85. }
adc.c文件主要进行ADC、DMA的初始化以及进行中断函数处理,注意此处在ADC初始化配置中,ADC的转换触发信号选择定时器触发,此处为定时器3.
main.c文件
  1. /********************************** (C) COPYRIGHT *******************************
  2. * File Name          : main.c
  3. * Author             : WCH
  4. * Version            : V1.0.0
  5. * Date               : 2020/04/30
  6. * Description        : Main program body.
  7. *******************************************************************************/

  8. /*
  9. *@Note
  10. ADC-DMA 多通道例程:
  11. 使用定时器3外部触发ADC转换。

  12. */

  13. #include "debug.h"
  14. #include "adc.h"
  15. #include "timer.h"

  16. /*******************************************************************************
  17. * Function Name  : main
  18. * Description    : Main program.
  19. * Input          : None
  20. * Return         : None
  21. *******************************************************************************/
  22. int main(void)
  23. {
  24.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  25.         Delay_Init();
  26.         USART_Printf_Init(115200);
  27.     Time_Init();
  28.     ADC_DMA_CONF();
  29.         printf("SystemClk:%d\r\n",SystemCoreClock);

  30.         while(1)
  31.         {

  32.         }
  33. }
main.c文件主要进行函数初始化。

4下载验证
将编译好的程序下载到开发版并复位,串口打印显示如下:
图片1.png

  

89、ADC-DMA-定时器触发中断,多通道.rar

518.03 KB, 下载次数: 302

豌豆爹 发表于 2021-5-6 15:53 | 显示全部楼层
很不错的,学习了解一下
您需要登录后才可以回帖 登录 | 注册

本版积分规则

133

主题

296

帖子

44

粉丝
快速回复 在线客服 返回列表 返回顶部

133

主题

296

帖子

44

粉丝
快速回复 在线客服 返回列表 返回顶部