硬汉嵌入式论坛

 找回密码
 立即注册
查看: 1244|回复: 3
收起左侧

【安富莱二代示波器教程】第6章 示波器设计—双通道ADC驱动

[复制链接]

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
发表于 2018-6-28 15:50:31 | 显示全部楼层 |阅读模式
本帖最后由 席萌0209 于 2018-6-28 15:52 编辑

完整教程下载地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=45785


第6章        示波器设计—双通道ADC驱动

    本章节为大家讲解示波器的ADC驱动,采用STM32自带ADC实现。关于STM32F429的ADC,可以说处处有地雷,不小心就踩上了,如果简单的使用,不会发现,复杂使用就很容易踩到了。
    6.1     3个ADC的快速交替采样
    6.2     双通道ADC采样
    6.3     拓展阅读
    6.4         总结


6.1  3个ADC的快速交替采样
    起初二代示波器是打算像一代示波器那样,准备做成3ADC(ADC1,ADC2和ADC3)快速交替采样,后期才改成双通道。这里将3ADC的各种奇葩问题也给大家做个说明,防止大家踩坑。
    3个ADC快速交替采样的两个可选的方案及其存在的问题。

6.1.1      方案一
    依然采用一代示波器那种方式,3个ADC都独立配置自己的DMA通道和相应的定时器进行触发。经过详细的测试发现,在最高采样率2.8Msps * 3 = 8.4Msps的情况下,F429的总线矩阵已经处理不过来了,导致的现象就是3个ADC中有两个已经停止工作。
    下面的测试都是在我们STM32-V6开发板上面进行的,主频168MHz。
1、测试方法
    直接调试状态看ADC1,2,3的三个大缓冲即可,看数据缓冲的数据是否在变化。
ADC1:
6.1.png
                              
ADC2:
6.2.png
ADC3:
6.3.png
(1)测试一
条件:
    开启ADC1,ADC2和ADC3及其配套的DMA,采用定时器触发,未开启emWin(要用到LTDC,DMA2D和FMC外接的SDRAM)。
现象:
    这种情况下,3个ADC可以正常工作。
(2测试二
条件:
    开启ADC1,ADC2和ADC3及其配套的DMA,采用定时器触发。仅使用ADC1,开启emWin(要用到LTDC,DMA2D和FMC外接的SDRAM)。
现象:
    ADC1在最高采样率2.8Msps的情况下,工作几秒钟,停止工作。
(3)测试三
条件:
    开启ADC1,ADC2和ADC3及其配套的DMA,采用定时器触发。仅使用ADC2,开启emWin(要用到LTDC,DMA2D和FMC外接的SDRAM)。
现象:
    ADC2在最高采样率2.8Msps的情况下,停止工作。
(4)测试四
条件:
    开启ADC1,ADC2和ADC3及其配套的DMA,采用定时器触发。仅使用ADC3,开启emWin(要用到LTDC,DMA2D和FMC外接的SDRAM)。
现象:
    ADC3在最高采样率2.8Msps的情况下,正常工作。
(5)测试五
条件:
    开启ADC1,ADC2和ADC3及其配套的DMA,采用定时器触发。同时使用ADC3,ADC2和ADC1,开启emWin(要用到LTDC,DMA2D和FMC外接的SDRAM)。
现象:
    每个ADC都是在最高采样率2.8Msps,刚开始ADC1还工作,过会ADC1停止工作,ADC2一直没有工作,ADC3一直在工作。
2、测试现象
    ADC工作不正常时,二代示波器波形显示效果如下:
6.4.png
3、总结
    对于STM32F429来说,如果三个ADC配合自己的DMA采用最高采样率2.8Msps * 3,且采用的定时器触发,在未使用emWin(要用到LTDC,DMA2D和FMC外接的SDRAM)时,可以正常工作,使用了的话,将会出现ADC1和ADC2不工作的情况。
    可能的原因是定时器触发太快,F429总线矩阵在这种情况下已经无法正常工作。

6.1.2      方案二
    采用F429自带的3个ADC快递交替采样模式,这个模式的问题最多,表现在以下三个方面:
(1)这种方式不能用于定时器触发,因为这三个ADC之间的采样间隔只有5个ADC时钟周期到20个ADC时钟周期可选,这样采用定时器触发的时候就没有办法做到等间隔采样。
(2)采集出来的波形效果比较差,基本没有使用价值。
(3)这种方式的3个ADC快递交替采样外加开启emWin(使能DMA2D,LTDC和FMC驱动的SDRAM),轻轻松松就将F429的总线矩阵干趴下了,直接导致ADC不工作了。
    测试条件:STM32-V6开发板,采用STM32F429支持的3个ADC快速交替采样,使能DMA,采用的软件触发。
(1)测试一
    配置采样率2.1Msps。
  1. /****************************************************************************  

  2.   PCLK2 = HCLK / 2

  3.   下面选择的是2分频

  4.   ADCCLK = PCLK2 /4 = HCLK / 4 = 168 / 4 = 42M

  5.   三ADC采样频率: 42 / 20 = 2.1Mbps

  6. *****************************************************************************/



  7. /* ADC公共部分初始化---------------------------------------------------------------*/

  8. ADC_CommonInitStructure.ADC_Mode = ADC_TripleMode_Interl;

  9. ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles;

  10. ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1;

  11. ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;

  12. ADC_CommonInit(&ADC_CommonInitStructure);
复制代码
凑合还能干活,但是显示效果很差:
6.5.png
(2)测试二
    配置采样率4.2Msps,直接停止工作。
  1. /****************************************************************************  

  2.   PCLK2 = HCLK / 2

  3.   下面选择的是2分频

  4.   ADCCLK = PCLK2 /4 = HCLK / 4 = 168 / 4 = 42M

  5.   三ADC采样频率: 42 / 10 = 4.2Mbps

  6. *****************************************************************************/



  7. /* ADC公共部分初始化---------------------------------------------------------------*/

  8. ADC_CommonInitStructure.ADC_Mode = ADC_TripleMode_Interl;

  9. ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_10Cycles;

  10. ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1;

  11. ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;

  12. ADC_CommonInit(&ADC_CommonInitStructure);
复制代码
显示效果直接死机:
6.6.png
总结
    相比于三个ADC独立配置实现快速交替采样,F429自带的这种3ADC快速交替采样的显示效果极其差,基本没有利用价值,而且最重要的是这种方式轻轻松松就将F429的总线矩阵干趴下了。结果就是ADC不干活了。
    再来欣赏下F429的总线矩阵长什么样子:
6.7.png

6.1.3     选择方案一还是方案二
    最终决定继续采用方案一,将最高采样率锁定在6Msps,这样才稳定些。


努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2018-6-28 15:55:31 | 显示全部楼层
6.2  双通道ADC采样
    相对于前面三通道ADC实现的快速交替采样,通过ADC1和ADC3实现双通道示波器,F429的硬件负担就稍轻松一些,不过依然存在一些问题。下面优先为大家说明ADC1和ADC3的驱动设计问题。
1、ADC1和ADC3被设置为定时器触发,DMA方式。其中ADC3使能了模拟看门狗,用于示波器上升沿的正常触发功能。另外,使用定时器触发是为了设置不同的采样率。
2、ADC2用于简单电压采集,未使用定时器和DMA。
  1. <font size="3">/*

  2. *********************************************************************************************************

  3. *    函 数 名: bsp_InitADC

  4. *    功能说明: ADC初始化

  5. *    形    参: 无

  6. *    返 回 值: 无

  7. *********************************************************************************************************

  8. */

  9. void bsp_InitADC(void)

  10. {

  11. ADC_InitTypeDef       ADC_InitStructure;

  12.     ADC_CommonInitTypeDef ADC_CommonInitStructure;

  13.     DMA_InitTypeDef       DMA_InitStructure;

  14.     GPIO_InitTypeDef      GPIO_InitStructure;

  15. NVIC_InitTypeDef NVIC_InitStructure;

  16.    

  17.     /* 配置模拟看门狗中断NVIC */

  18.     NVIC_InitStructure.NVIC_IRQChannel = ADC_IRQn;

  19.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

  20.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

  21.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  22.     NVIC_Init(&NVIC_InitStructure);

  23.    

  24.     /* 使能 ADC1, ADC2, ADC3,DMA2 和 GPIO 时钟 ****************************************/

  25.     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOC, ENABLE);

  26.      RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2 | RCC_APB2Periph_ADC3, ENABLE);

  27.    

  28.      /* DMA2 Stream1 channel1 配置用于ADC3 **************************************/

  29.      //DMA_DeInit(DMA2_Stream1);

  30.     DMA_InitStructure.DMA_Channel = DMA_Channel_2;

  31.      DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC3_DR_ADDRESS;

  32.      DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC3ConvertedValue;

  33.      DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;

  34.      DMA_InitStructure.DMA_BufferSize = 1024*10;

  35.      DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

  36.      DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

  37.      DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

  38.      DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_HalfWord;

  39.      DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

  40.      DMA_InitStructure.DMA_Priority = DMA_Priority_High;

  41.      DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;        

  42.      DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;

  43.      DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;

  44.      DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

  45.      DMA_Init(DMA2_Stream1, &DMA_InitStructure);

  46.      DMA_Cmd(DMA2_Stream1, ENABLE);

  47.    

  48.      /* DMA2 Stream0 channel0 配置用于ADC1 **************************************/

  49.      //DMA_DeInit(DMA2_Stream0);

  50.      DMA_InitStructure.DMA_Channel = DMA_Channel_0;

  51.      DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_ADDRESS;

  52.      DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC1ConvertedValue;

  53.      DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;

  54.      DMA_InitStructure.DMA_BufferSize = 1024*10;

  55.      DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

  56.      DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

  57.      DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

  58.      DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_HalfWord;

  59.      DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

  60.      DMA_InitStructure.DMA_Priority = DMA_Priority_High;

  61.      DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;        

  62.      DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;

  63.      DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;

  64.      DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

  65.      DMA_Init(DMA2_Stream0, &DMA_InitStructure);

  66.      DMA_Cmd(DMA2_Stream0, ENABLE);



  67.     /* 配置ADC引脚为模拟输入模式******************************/

  68.      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;

  69.      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;

  70.      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;

  71.      GPIO_Init(GPIOC, &GPIO_InitStructure);

  72.    

  73.      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;

  74.      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;

  75.      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;

  76.      GPIO_Init(GPIOC, &GPIO_InitStructure);

  77.         

  78.     /*

  79.      ***************************************************************************  

  80.        PCLK2 = HCLK / 2

  81.        下面选择的是2分频

  82.        ADCCLK = PCLK2 /2 = HCLK / 4 = 168 / 4 = 42M

  83.       ADC采样频率: Sampling Time + Conversion Time = 3 + 12 cycles = 15cyc

  84.                     Conversion Time = 42MHz / 15cyc = 2.8Mbps.

  85.      ****************************************************************************

  86.      */

  87.    

  88.     /* ADC公共部分初始化**********************************************************/

  89.     ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;

  90.     ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_8Cycles;

  91.     ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;

  92.     ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;

  93.     ADC_CommonInit(&ADC_CommonInitStructure);

  94.    

  95.      /////////////////////////////////////////////////////////////////////////////////////////////////

  96.      /////////////////////////////////////////////////////////////////////////////////////////////////



  97.       /*ADC3的配置*****************************************************************/

  98.      ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;

  99.      ADC_InitStructure.ADC_ScanConvMode = DISABLE;

  100.      ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;

  101.      ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;

  102.      ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC3;

  103.      ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

  104.      ADC_InitStructure.ADC_NbrOfConversion = 1;

  105.    

  106.     /* ADC3 规则通道配置 */

  107.      ADC_Init(ADC3, &ADC_InitStructure);

  108.      ADC_RegularChannelConfig(ADC3, ADC_Channel_10, 1, ADC_SampleTime_3Cycles);



  109.     /* 使能 ADC3 DMA */

  110.      ADC_DMACmd(ADC3, ENABLE);

  111.    

  112.      /* 配置模拟看门狗的阀值 注意别配置反了,要不一直进入中断 */

  113.     ADC_AnalogWatchdogThresholdsConfig(ADC3, 4095, 0);

  114.    

  115.     /* 配置模拟看门狗监测ADC3的通道10 */

  116.     ADC_AnalogWatchdogSingleChannelConfig(ADC3, ADC_Channel_10);

  117.    

  118.     /* 使能一个规则通道的看门狗 */

  119.     ADC_AnalogWatchdogCmd(ADC3, ADC_AnalogWatchdog_SingleRegEnable);



  120.     /* 使能模拟看门狗中断 */

  121.     ADC_ITConfig(ADC3, ADC_IT_AWD, ENABLE);

  122.    

  123.      /* 使能DMA请求 (多ADC模式) --------------------------------------------------*/

  124.      ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE);



  125.      /* Enable ADC1 --------------------------------------------------------------*/

  126.      ADC_Cmd(ADC3, ENABLE);

  127.    

  128.      /////////////////////////////////////////////////////////////////////////////////////////////////

  129.      /////////////////////////////////////////////////////////////////////////////////////////////////

  130.    

  131.      /*ADC1的配置******************************************************************/

  132.     ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;

  133.      ADC_InitStructure.ADC_ScanConvMode = DISABLE;

  134.      ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;

  135.      ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;

  136.     ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;

  137.      ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

  138.      ADC_InitStructure.ADC_NbrOfConversion = 1;

  139.    

  140.     /* ADC1 规则通道配置 -------------------------------------------------------*/

  141.      ADC_Init(ADC1, &ADC_InitStructure);

  142.      ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 1, ADC_SampleTime_3Cycles);



  143.     /* 使能 ADC1 DMA */

  144.      ADC_DMACmd(ADC1, ENABLE);

  145.    

  146.      /* 使能DMA请求 (多ADC模式) --------------------------------------------------*/

  147.      ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);



  148.      /* Enable ADC1 --------------------------------------------------------------*/

  149.      ADC_Cmd(ADC1, ENABLE);

  150.    

  151.      /////////////////////////////////////////////////////////////////////////////////////////////////

  152.      /////////////////////////////////////////////////////////////////////////////////////////////////



  153.     /*ADC2的配置*****************************************************************/

  154.     ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;

  155.      ADC_InitStructure.ADC_ScanConvMode = DISABLE;

  156.      ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;

  157.      ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;

  158.     ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC2;

  159.      ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

  160.      ADC_InitStructure.ADC_NbrOfConversion = 1;

  161.    

  162.     /* ADC2 规则通道配置 */

  163.      ADC_Init(ADC2, &ADC_InitStructure);

  164.      ADC_RegularChannelConfig(ADC2, ADC_Channel_10, 1, ADC_SampleTime_480Cycles);



  165.      /* 使能 ADC2 */

  166.      ADC_Cmd(ADC2, ENABLE);

  167.    

  168.      /**定时器配置********************************************************************/

  169.      TIM1_Config();

  170. }</font>
复制代码
使用这个驱动要注意以下四个问题:
1、当前ADC1和ADC3的DMA缓冲区都设置了10240个,这个大小已经够用。
2、DMA的FIFO功能一定要关闭,这是一个大坑。详情在这个帖子里面做了总结,必看:http://www.armbbs.cn/forum.php?mod=viewthread&tid=77359
3、ADC的采样率不要设置低了,ADC设置的时钟速度一定要大于等于定时器触发速度。当前ADC1和ADC3配置的采样率都是2.8Msps。如果设置的定时器触发速度大于这个,ADC的采样速度是跟不上的。
4、ADC2的配置没有使用外部定时器触发和DMA,而且这里关闭了连续采样
    ADC_InitStructure.ADC_ContinuousConvMode= DISABLE。
    如果用户使能为连续转换,调用函数ADC_SoftwareStartConv(ADC2)做一次软件触发即可。而我们将其关闭掉,触发一次读取一次,更方便些,适合做一些慢速的电压测量的工作。
   

      说完了上面的问题,还有一个定时器触发的问题,看下面的驱动代码:
  1. <font size="3">/*

  2. *********************************************************************************************************

  3. *    函 数 名: TIM1_Config

  4. *    功能说明: 配置定时器1,用于触发ADC1和ADC3。

  5. *             当外部触发信号被选为ADC规则或注入转换时,只有它的上升沿可以启动转换。

  6. *    形    参: 无

  7. *    返 回 值: 无

  8. *********************************************************************************************************

  9. */

  10. static void TIM1_Config(void)

  11. {

  12.     TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

  13.     TIM_OCInitTypeDef  TIM_OCInitStructure;

  14.    

  15.      /* 使能定时器1 */

  16.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);   

  17.    

  18.      /* 先禁能再配置 */

  19.     TIM_Cmd(TIM1, DISABLE);

  20.    

  21.     /*

  22.      ********************************************************************************

  23.     system_stm32f4xx.c 文件中 void SetSysClock(void) 函数对时钟的配置如下:



  24.     HCLK = SYSCLK / 1     (AHB1Periph)

  25.     PCLK2 = HCLK / 2      (APB2Periph)

  26.     PCLK1 = HCLK / 4      (APB1Periph)



  27.     因为APB1 prescaler != 1, 所以 APB1上的TIMxCLK = PCLK1 x 2 = SystemCoreClock / 2;

  28.     因为APB2 prescaler != 1, 所以 APB2上的TIMxCLK = PCLK2 x 2 = SystemCoreClock;



  29.     APB1 定时器有 TIM2, TIM3 ,TIM4, TIM5, TIM6, TIM7, TIM12, TIM13, TIM14

  30.     APB2 定时器有 TIM1, TIM8 ,TIM9, TIM10, TIM11

  31.          

  32.     TIM1 更新周期是 = TIM1CLK / (TIM_Period + 1)/(TIM_Prescaler + 1)

  33.     ********************************************************************************

  34.     */

  35.     //初始化定时器1的寄存器为复位值

  36. TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);

  37. //ARR自动重装载寄存器周期的值(定时时间)到设置频率后产生个更新或者中断(也是说定时时间到)

  38. TIM_TimeBaseStructure.TIM_Period =  168000000/g_SampleFreqTable[TimeBaseId][0] - 1;

  39. //PSC时钟预分频数 例如:时钟频率=TIM1CLK/(时钟预分频+1)

  40. TIM_TimeBaseStructure.TIM_Prescaler = g_SampleFreqTable[TimeBaseId][1]-1;

  41. TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;                 //CR1->CKD时间分割值

  42.     TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;     //CR1->CMS[1:0]和DIR定时器模式 向上计数

  43. TIM_TimeBaseStructure.TIM_RepetitionCounter = 0x0000;          /* TIM1 和 TIM8 必须设置 */   

  44.     TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);



  45.     /**************ADC1的触发***********************************************/

  46.     //CCMR2在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为有效电平,否则为无效电平

  47. TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;                  

  48. TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;  //CCER 输出使能

  49. //CCR3同计数器TIMx_CNT的比较,并在OC1端口上产生输出信号           

  50. TIM_OCInitStructure.TIM_Pulse = TIM_TimeBaseStructure.TIM_Period/2;  

  51. TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;       //CCER输出极性设置

  52. /* only for TIM1 and TIM8. 此处和正相引脚不同 */   

  53. TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;

  54. TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;   /* only for TIM1 and TIM8. */

  55. TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; /* only for TIM1 and TIM8. */

  56. TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;/* only for TIM1 and TIM8. */  

  57. TIM_OC1Init(TIM1, &TIM_OCInitStructure);

  58.    

  59.      /**************ADC3的触发***********************************************/

  60. TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;                  

  61.     TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;   

  62.     TIM_OCInitStructure.TIM_Pulse = TIM_TimeBaseStructure.TIM_Period-1;

  63. TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;

  64. /* only for TIM1 and TIM8. 此处和正相引脚不同 */   

  65. TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;   

  66. TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;  /* only for TIM1 and TIM8. */

  67. TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; /* only for TIM1 and TIM8. */

  68. TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;/* only for TIM1 and TIM8. */      

  69.     TIM_OC3Init(TIM1, &TIM_OCInitStructure);

  70.     //TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable); //CMR2 设置预装载使能  更新事件产生时写入有效

  71.     //TIM_ARRPreloadConfig(TIM1, ENABLE);               //CR1  设置ARR自动重装 更新事件产生时写入有效

  72.     TIM_Cmd(TIM1, ENABLE);

  73.    

  74.     /* 使能PWM输出 */

  75.     TIM_CtrlPWMOutputs(TIM1, ENABLE);         

  76. }</font>
复制代码
关于这个驱动设计,注意以下三个问题:
1、定时器TIM1是16位定时器,下面两个参数的配置切勿超过65535。
    TIM_TimeBaseStructure.TIM_Period
    TIM_TimeBaseStructure.TIM_Prescaler
2、关于定时器触发的配置,要特别注意下面参数的设置:
    TIM_OCInitStructure.TIM_Pulse
    如果大家将TIM1的OC1和OC3设置成一样的,那么定时器的触发频率大于2MHz时,很容易导致ADC触发失败。而且这种触发失败的现象还比较神奇,程序初始的触发频率大于2MHz,上电后导致ADC触发失败,但是切换几次不同频率,再切换回来,又正常工作了。为了安全起见这里将其区分开了。
3、另外使用TIM1或者TIM8做ADC采样触发,要注意结构体成员的配置,这两个定时器比其他定时器多一些参数要配置,大家配置的时候切勿忘记初始化,因为我们这里用的是局部变量,未初始化的话,它的值是随机的。
    TIM_OCInitStructure.TIM_OutputNState= TIM_OutputNState_Enable;
    TIM_OCInitStructure.TIM_OCNPolarity= TIM_OCNPolarity_High;               TIM_OCInitStructure.TIM_OCIdleState =TIM_OCIdleState_Reset;          TIM_OCInitStructure.TIM_OCNIdleState= TIM_OCNIdleState_Reset;

努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2018-6-28 15:57:08 | 显示全部楼层
6.3   拓展阅读
    ADC的外部输入阻抗只有50KΩ,大家测量时要特别注意。另外,这里重点推荐两篇提高ADC精度的文档,是ST官方做的,对于阻抗和精度问题做了详细说明,下载地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=82543

努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2018-6-28 15:57:54 | 显示全部楼层
6.4  总结
    关于ADC的驱动就为大家讲解这么多,一定要实际操作配置下。如果需要ADC其它的配置方式,在我们论坛置顶帖STM32-V5的裸机例子基础篇里面下载即可:http://www.armbbs.cn/forum.php?mod=viewthread&tid=1285
6.8.png

努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-13 03:19 , Processed in 0.164948 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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