查看: 1272|回复: 0
收起左侧

第三十六章:CH32V103应用教程——ADC-间断模式

[复制链接]

  离线 

  • TA的每日心情
    慵懒
    2021-7-23 17:16
  • 签到天数: 17 天

    [LV.4]

    发表于 2021-4-27 20:52:26 | 显示全部楼层 |阅读模式

    有人预言,RISC-V或将是继Intel和Arm之后的第三大主流处理器体系。欢迎访问全球首家只专注于RISC-V单片机行业应用的中文网站

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    本帖最后由 草帽王子 于 2021-9-10 17:22 编辑

    本章主要在前面章节基础上进行ADC间断模式实验。


    1、ADC简介及相关函数介绍

    通过设置ADC控制寄存器1(ADC_CTLR1)的RDISCEN(规则通道的间断模式使能位)或IDISCEN(注入通道模式上的间断使能位)位为1进入规则组或注入组的间断模式。此模式区别扫描模式中扫描完整的一组通道,而是将一组通道分为多个短序列,每次外部触发事件将执行一个短序列的扫描转换。

    短序列的长度n(n<=8)定义在ADC_CTLR1 寄存器的(间断模式下,外部触发后要转换的规则通道数目)DISCNUM[2:0]中,当RDISCEN为1,则是规则组的间断模式,待转换总长度定义在ADC_RSQR1 寄存器(ADC规则通道序列寄存器1)的RLEN[3:0](规则通道转换序列中需要转换的通道数目)中;当IDISCEN为1,则是注入组的间断模式,待转换总长度定义在ADC_ISQR寄存器(ADC注入通道序列寄存器)的ILEN[1:0](注入通道转换序列中需要转换的通道数目)中。不能同时将规则组和注入组设置为间断模式。

    规则组间断模式举例:
    RDISCEN=1,DISCNUM[2:0]=3,RLEN[3:0]=8,待转换通道=1,3,2,5,8,4,10,6
    第 1 次外部触发:转换序列为:1,3,2
    第 2 次外部触发:转换序列为:5,8,4
    第 3 次外部触发:转换序列为:10,6,同时产生 EOC 事件
    第 4 次外部触发:转换序列为:1,3,2

    注入组间断模式举例:
    IDISCEN=1,DISCNUM[2:0]=1,ILEN[1:0]=3,待转换通道=1,3,2
    第 1 次外部触发:转换序列为:1
    第 2 次外部触发:转换序列为:3
    第 3 次外部触发:转换序列为:2,同时产生 EOC 和 IEOC 事件
    第 4 次外部触发:转换序列为:1

    注:
      1.当以间断模式转换一个规则组或注入组时,转换序列结束后不自动从头开始。当所有子组被转换完成,下一次触发事件启动第一个子组的转换。
      2.不能同时使用自动注入(IAUTO=1)和间断模式。
      3.不能同时为规则组和注入组设置间断模式,间断模式只能用于一组转换。


    2、硬件设计

    本章教程主要进行注入组间断模式实验,当定时器产生更新时间触发AD转换,因此需要用到ADC1通道2-4(即PA2-4)以及定时器对应引脚。测试时将PA2-4引脚与3.3V引脚或GND引脚连接即可。此外,由于定时器触发事件属于来自片上定时器的内部信号,无需进行硬件连接。


    3、软件设计

    本章主要进行ADC间断模式实验,本章教程在第八章PWM输出以及第三十五章基础上进行,相关内容可参考前面章节。ADC间断模式应用程序具体如下:
    adc.h文件
    1. #ifndef __ADC_H
    2. #define __ADC_H

    3. #include "ch32v10x_conf.h"

    4. void ADC_Function_Init(void);
    5. void TIM1_PWM_In( u16 arr, u16 psc, u16 ccp );

    6. #endif
    复制代码
    adc.h文件主要进行函数的声明;
    adc.c文件
    1. #include "adc.h"

    2. /*******************************************************************************
    3. * Function Name  : ADC_Function_Init
    4. * Description    : Initializes ADC collection.
    5. * Input          : None
    6. * Return         : None
    7. *******************************************************************************/
    8. void ADC_Function_Init(void)
    9. {
    10.     GPIO_InitTypeDef GPIO_InitStructure;
    11.     ADC_InitTypeDef  ADC_InitStructure;

    12.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1, ENABLE );

    13.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    14.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入模式
    15.     GPIO_Init(GPIOA, &GPIO_InitStructure);

    16.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
    17.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入模式
    18.     GPIO_Init(GPIOA, &GPIO_InitStructure);

    19.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    20.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入模式
    21.     GPIO_Init(GPIOA, &GPIO_InitStructure);

    22.     RCC_ADCCLKConfig(RCC_PCLK2_Div6);

    23.     ADC_DeInit(ADC1);
    24.     ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
    25.     ADC_InitStructure.ADC_ScanConvMode = DISABLE;
    26.     ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
    27.     ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigInjecConv_T1_CC4; //注入通道组外部触发,定时器1的CC4事件
    28.     ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    29.     ADC_InitStructure.ADC_NbrOfChannel = 3;
    30.     ADC_Init(ADC1, &ADC_InitStructure);

    31.     ADC_InjectedSequencerLengthConfig(ADC1, 3); //配置注入通道序列长度为3
    32.     ADC_InjectedChannelConfig(ADC1, ADC_Channel_2, 1, ADC_SampleTime_239Cycles5); //为所选ADC注入通道配置其转换顺序及其采样时间
    33.     ADC_InjectedChannelConfig(ADC1, ADC_Channel_3, 2, ADC_SampleTime_239Cycles5);
    34.     ADC_InjectedChannelConfig(ADC1, ADC_Channel_4, 3, ADC_SampleTime_239Cycles5);

    35.     ADC_DiscModeChannelCountConfig( ADC1, 1); //间断模式配置
    36.     ADC_InjectedDiscModeCmd(ADC1 , ENABLE);   //开启注入通道间断模式
    37.     ADC_ExternalTrigInjectedConvCmd(ADC1, ENABLE); //开启注入通道外部触发转换
    38.     ADC_Cmd(ADC1, ENABLE);

    39.     ADC_ResetCalibration(ADC1);
    40.     while(ADC_GetResetCalibrationStatus(ADC1));
    41.     ADC_StartCalibration(ADC1);
    42.     while(ADC_GetCalibrationStatus(ADC1));
    43. }

    44. /*******************************************************************************
    45. * Function Name  : TIM1_PWM_In
    46. * Description    : Initializes TIM1 PWM output.
    47. * Input          : arr: the period value.
    48. *                  psc: the prescaler value.
    49. *                                    ccp: the pulse value.
    50. * Return         : None
    51. *******************************************************************************/
    52. void TIM1_PWM_In( u16 arr, u16 psc, u16 ccp )
    53. {
    54.     GPIO_InitTypeDef GPIO_InitStructure;
    55.     TIM_OCInitTypeDef TIM_OCInitStructure;
    56.     TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;

    57.     RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_TIM1, ENABLE );

    58.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
    59.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    60.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    61.     GPIO_Init( GPIOA, &GPIO_InitStructure);

    62.     TIM_TimeBaseInitStructure.TIM_Period = arr;                      //设置重装载值
    63.     TIM_TimeBaseInitStructure.TIM_Prescaler = psc;                   //设置预分频值
    64.     TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;      //分频系数
    65.     TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;  //计数模式:向上计数
    66.     TIM_TimeBaseInit( TIM1, &TIM_TimeBaseInitStructure);

    67.     TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;                //TIM模式为PWM输出模式
    68.     TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;    //使能比较输出
    69.     TIM_OCInitStructure.TIM_Pulse = ccp;                             //指定要加载到捕获比较寄存器中的脉冲值
    70.     TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;         //设置输出极性:低
    71.     TIM_OC4Init( TIM1, &TIM_OCInitStructure );

    72.     TIM_CtrlPWMOutputs(TIM1, ENABLE );
    73.     TIM_OC4PreloadConfig( TIM1, TIM_OCPreload_Disable );  //禁用CH4预装载使能
    74.     TIM_ARRPreloadConfig( TIM1, ENABLE );
    75.     TIM_SelectOutputTrigger( TIM1, TIM_TRGOSource_Update ); //定时器触发输出,定时器产生更新事件触发AD转换
    76.     TIM_Cmd( TIM1, ENABLE );
    77. }
    复制代码

    adc.c文件主要进行ADC相关初始化配置以及PWM输出配置,与前面章节相比,主要进行以下改动:
    开启注入通道组外部触发:
    1. ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigInjecConv_T1_CC4; //注入通道组外部触发,定时器1的CC4事件
    复制代码

    进行注入通道相关配置以及进行间断模式等相关配置:
    1.     ADC_InjectedSequencerLengthConfig(ADC1, 3); //配置注入通道序列长度为3
    2.     ADC_InjectedChannelConfig(ADC1, ADC_Channel_2, 1, ADC_SampleTime_239Cycles5); //为所选ADC注入通道配置其转换顺序及其采样时间
    3.     ADC_InjectedChannelConfig(ADC1, ADC_Channel_3, 2, ADC_SampleTime_239Cycles5);
    4.     ADC_InjectedChannelConfig(ADC1, ADC_Channel_4, 3, ADC_SampleTime_239Cycles5);

    5.     ADC_DiscModeChannelCountConfig( ADC1, 1); //间断模式配置
    6.     ADC_InjectedDiscModeCmd(ADC1 , ENABLE);   //开启注入通道间断模式
    7.     ADC_ExternalTrigInjectedConvCmd(ADC1, ENABLE); //开启注入通道外部触发转换
    复制代码

    PWM输出函数与之前相比,进行定时器触发输出配置,触发AD转换:
    1. TIM_SelectOutputTrigger( TIM1, TIM_TRGOSource_Update ); //定时器触发输出,定时器产生更新事件触发AD转换
    复制代码

    main.c文件
    1. int main(void)
    2. {
    3.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    4.         Delay_Init();
    5.         USART_Printf_Init(115200);

    6.         ADC_Function_Init();
    7.         TIM1_PWM_In( 1000, 48000-1, 500 );

    8.         printf("SystemClk:%d\r\n",SystemCoreClock);

    9.         printf("This is printf example\r\n");

    10.         while(1)
    11.         {
    12.         while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));
    13.         ADC_ClearFlag( ADC1, ADC_FLAG_EOC);
    14.         while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_JEOC ));
    15.         ADC_ClearFlag( ADC1, ADC_FLAG_JEOC);

    16.         printf("ADC Discontinuous injected group conversion...\r\n");
    17.         printf( "%d\r\n", ADC1->IDATAR1 );
    18.         printf( "%d\r\n", ADC1->IDATAR2 );
    19.         printf( "%d\r\n", ADC1->IDATAR3 );

    20.         }
    21. }
    复制代码
    main.c文件主要进行函数初始化以及注入通道ADC值打印输出。


    4、下载验证

    将编译好的程序下载到开发板并复位,其中,PA2接GND引脚,PA3-4接3.3V引脚,串口显示如下:
    CH32V CH573单片机芯片-第三十六章:CH32V103应用教程——ADC-间断模式risc-v单片机中文社区(1)

    ADC-间断模式.rar
    CH32V CH573单片机芯片-第三十六章:CH32V103应用教程——ADC-间断模式risc-v单片机中文社区(2) 35、ADC-间断模式.rar (494.99 KB, 下载次数: 10)
    链接:https://pan.baidu.com/s/1q1CVMQY8InKi6FF-oQxXEw
    提取码:fz2r
    复制这段内容后打开百度网盘手机App,操作更方便哦







    上一篇:第三十五章:CH32V103应用教程——ADC-注入通道管理
    下一篇:第三十七章:CH32V103应用教程——I2C-软件模拟I2C读写EEPROM
    RISCV作者优文
    全球首家只专注于RISC-V单片机行业应用的中文网站
    回复

    使用道具 举报

    高级模式
    B Color Image Link Quote Code Smilies

    本版积分规则

    关闭

    RISC-V单片机中文网上一条 /2 下一条



    版权及免责声明|RISC-V单片机中文网 |网站地图

    GMT+8, 2024-4-25 17:45 , Processed in 0.840250 second(s), 48 queries .

    快速回复 返回顶部 返回列表