【安富莱二代示波器教程】第6章 示波器设计—双通道ADC驱动
第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。
测试方法
直接调试状态看ADC1,2,3的三个大缓冲即可,看数据缓冲的数据是否在变化。
ADC1:
ADC2:
ADC3:
(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一直在工作。
测试现象
ADC工作不正常时,二代示波器波形显示效果如下:
总结
对于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,采用的软件触发。
测试一
配置采样率2.1Msps。
/**************************************************************************** PCLK2 = HCLK / 2 下面选择的是2分频 ADCCLK = PCLK2 /4 = HCLK / 4 = 168 / 4 = 42M 三ADC采样频率: 42 / 20 = 2.1Mbps *****************************************************************************/ /* ADC公共部分初始化---------------------------------------------------------------*/ ADC_CommonInitStructure.ADC_Mode = ADC_TripleMode_Interl; ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles; ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1; ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; ADC_CommonInit(&ADC_CommonInitStructure);
凑合还能干活,但是显示效果很差:
测试二
配置采样率4.2Msps,直接停止工作。
/**************************************************************************** PCLK2 = HCLK / 2 下面选择的是2分频 ADCCLK = PCLK2 /4 = HCLK / 4 = 168 / 4 = 42M 三ADC采样频率: 42 / 10 = 4.2Mbps *****************************************************************************/ /* ADC公共部分初始化---------------------------------------------------------------*/ ADC_CommonInitStructure.ADC_Mode = ADC_TripleMode_Interl; ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_10Cycles; ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1; ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; ADC_CommonInit(&ADC_CommonInitStructure);
显示效果直接死机:
总结
相比于三个ADC独立配置实现快速交替采样,F429自带的这种3ADC快速交替采样的显示效果极其差,基本没有利用价值,而且最重要的是这种方式轻轻松松就将F429的总线矩阵干趴下了。结果就是ADC不干活了。
再来欣赏下F429的总线矩阵长什么样子:
6.1.3 选择方案一还是方案二
最终决定继续采用方案一,将最高采样率锁定在6Msps,这样才稳定些。
6.2 双通道ADC采样
相对于前面三通道ADC实现的快速交替采样,通过ADC1和ADC3实现双通道示波器,F429的硬件负担就稍轻松一些,不过依然存在一些问题。下面优先为大家说明ADC1和ADC3的驱动设计问题。
1、ADC1和ADC3被设置为定时器触发,DMA方式。其中ADC3使能了模拟看门狗,用于示波器上升沿的正常触发功能。另外,使用定时器触发是为了设置不同的采样率。
2、ADC2用于简单电压采集,未使用定时器和DMA。
/* ********************************************************************************************************* * 函 数 名: bsp_InitADC * 功能说明: ADC初始化 * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ void bsp_InitADC(void) { ADC_InitTypeDef ADC_InitStructure; ADC_CommonInitTypeDef ADC_CommonInitStructure; DMA_InitTypeDef DMA_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; /* 配置模拟看门狗中断NVIC */ NVIC_InitStructure.NVIC_IRQChannel = ADC_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = ; NVIC_InitStructure.NVIC_IRQChannelSubPriority = ; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /* 使能 ADC1, ADC2, ADC3,DMA2 和 GPIO 时钟 ****************************************/ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOC, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2 | RCC_APB2Periph_ADC3, ENABLE); /* DMA2 Stream1 channel1 配置用于ADC3 **************************************/ //DMA_DeInit(DMA2_Stream1); DMA_InitStructure.DMA_Channel = DMA_Channel_2; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC3_DR_ADDRESS; DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC3ConvertedValue; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; DMA_InitStructure.DMA_BufferSize = *; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init(DMA2_Stream1, &DMA_InitStructure); DMA_Cmd(DMA2_Stream1, ENABLE); /* DMA2 Stream0 channel0 配置用于ADC1 **************************************/ //DMA_DeInit(DMA2_Stream0); DMA_InitStructure.DMA_Channel = DMA_Channel_0; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_ADDRESS; DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC1ConvertedValue; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; DMA_InitStructure.DMA_BufferSize = *; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init(DMA2_Stream0, &DMA_InitStructure); DMA_Cmd(DMA2_Stream0, ENABLE); /* 配置ADC引脚为模拟输入模式******************************/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; GPIO_Init(GPIOC, &GPIO_InitStructure); /* *************************************************************************** PCLK2 = HCLK / 2 下面选择的是2分频 ADCCLK = PCLK2 /2 = HCLK / 4 = 168 / 4 = 42M ADC采样频率: Sampling Time + Conversion Time = 3 + 12 cycles = 15cyc Conversion Time = 42MHz / 15cyc = 2.8Mbps. **************************************************************************** */ /* ADC公共部分初始化**********************************************************/ ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_8Cycles; ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; ADC_CommonInit(&ADC_CommonInitStructure); ///////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////// /*ADC3的配置*****************************************************************/ ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC3; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfConversion = ; /* ADC3 规则通道配置 */ ADC_Init(ADC3, &ADC_InitStructure); ADC_RegularChannelConfig(ADC3, ADC_Channel_10, , ADC_SampleTime_3Cycles); /* 使能 ADC3 DMA */ ADC_DMACmd(ADC3, ENABLE); /* 配置模拟看门狗的阀值 注意别配置反了,要不一直进入中断 */ ADC_AnalogWatchdogThresholdsConfig(ADC3, , ); /* 配置模拟看门狗监测ADC3的通道10 */ ADC_AnalogWatchdogSingleChannelConfig(ADC3, ADC_Channel_10); /* 使能一个规则通道的看门狗 */ ADC_AnalogWatchdogCmd(ADC3, ADC_AnalogWatchdog_SingleRegEnable); /* 使能模拟看门狗中断 */ ADC_ITConfig(ADC3, ADC_IT_AWD, ENABLE); /* 使能DMA请求 (多ADC模式) --------------------------------------------------*/ ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE); /* Enable ADC1 --------------------------------------------------------------*/ ADC_Cmd(ADC3, ENABLE); ///////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////// /*ADC1的配置******************************************************************/ ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfConversion = ; /* ADC1 规则通道配置 -------------------------------------------------------*/ ADC_Init(ADC1, &ADC_InitStructure); ADC_RegularChannelConfig(ADC1, ADC_Channel_13, , ADC_SampleTime_3Cycles); /* 使能 ADC1 DMA */ ADC_DMACmd(ADC1, ENABLE); /* 使能DMA请求 (多ADC模式) --------------------------------------------------*/ ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE); /* Enable ADC1 --------------------------------------------------------------*/ ADC_Cmd(ADC1, ENABLE); ///////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////// /*ADC2的配置*****************************************************************/ ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC2; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfConversion = ; /* ADC2 规则通道配置 */ ADC_Init(ADC2, &ADC_InitStructure); ADC_RegularChannelConfig(ADC2, ADC_Channel_10, , ADC_SampleTime_480Cycles); /* 使能 ADC2 */ ADC_Cmd(ADC2, ENABLE); /**定时器配置********************************************************************/ TIM1_Config(); }
使用这个驱动要注意以下四个问题:
(1)当前ADC1和ADC3的DMA缓冲区都设置了10240个,这个大小已经够用。
(2)DMA的FIFO功能一定要关闭,这是一个大坑。详情在这个帖子里面做了总结,必看:
http://forum.armfly.com/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)做一次软件触发即可。而我们将其关闭掉,触发一次读取一次,更方便些,适合做一些慢速的电压测量的工作。
说完了上面的问题,还有一个定时器触发的问题,看下面的驱动代码:
/* ********************************************************************************************************* * 函 数 名: TIM1_Config * 功能说明: 配置定时器1,用于触发ADC1和ADC3。 * 当外部触发信号被选为ADC规则或注入转换时,只有它的上升沿可以启动转换。 * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ static void TIM1_Config(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; /* 使能定时器1 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); /* 先禁能再配置 */ TIM_Cmd(TIM1, DISABLE); /* ******************************************************************************** system_stm32f4xx.c 文件中 void SetSysClock(void) 函数对时钟的配置如下: HCLK = SYSCLK / 1 (AHB1Periph) PCLK2 = HCLK / 2 (APB2Periph) PCLK1 = HCLK / 4 (APB1Periph) 因为APB1 prescaler != 1, 所以 APB1上的TIMxCLK = PCLK1 x 2 = SystemCoreClock / 2; 因为APB2 prescaler != 1, 所以 APB2上的TIMxCLK = PCLK2 x 2 = SystemCoreClock; APB1 定时器有 TIM2, TIM3 ,TIM4, TIM5, TIM6, TIM7, TIM12, TIM13, TIM14 APB2 定时器有 TIM1, TIM8 ,TIM9, TIM10, TIM11 TIM1 更新周期是 = TIM1CLK / (TIM_Period + 1)/(TIM_Prescaler + 1) ******************************************************************************** */ //初始化定时器1的寄存器为复位值 TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); //ARR自动重装载寄存器周期的值(定时时间)到设置频率后产生个更新或者中断(也是说定时时间到) TIM_TimeBaseStructure.TIM_Period = /g_SampleFreqTable[TimeBaseId][] - ; //PSC时钟预分频数 例如:时钟频率=TIM1CLK/(时钟预分频+1) TIM_TimeBaseStructure.TIM_Prescaler = g_SampleFreqTable[TimeBaseId][]-; TIM_TimeBaseStructure.TIM_ClockDivision = 0x0; //CR1->CKD时间分割值 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //CR1->CMS[1:0]和DIR定时器模式 向上计数 TIM_TimeBaseStructure.TIM_RepetitionCounter = 0x0000; /* TIM1 和 TIM8 必须设置 */ TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); /**************ADC1的触发***********************************************/ //CCMR2在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为有效电平,否则为无效电平 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //CCER 输出使能 //CCR3同计数器TIMx_CNT的比较,并在OC1端口上产生输出信号 TIM_OCInitStructure.TIM_Pulse = TIM_TimeBaseStructure.TIM_Period/; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //CCER输出极性设置 /* only for TIM1 and TIM8. 此处和正相引脚不同 */ TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; /* only for TIM1 and TIM8. */ TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; /* only for TIM1 and TIM8. */ TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;/* only for TIM1 and TIM8. */ TIM_OC1Init(TIM1, &TIM_OCInitStructure); /**************ADC3的触发***********************************************/ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = TIM_TimeBaseStructure.TIM_Period-; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; /* only for TIM1 and TIM8. 此处和正相引脚不同 */ TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; /* only for TIM1 and TIM8. */ TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; /* only for TIM1 and TIM8. */ TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;/* only for TIM1 and TIM8. */ TIM_OC3Init(TIM1, &TIM_OCInitStructure); //TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable); //CMR2 设置预装载使能 更新事件产生时写入有效 //TIM_ARRPreloadConfig(TIM1, ENABLE); //CR1 设置ARR自动重装 更新事件产生时写入有效 TIM_Cmd(TIM1, ENABLE); /* 使能PWM输出 */ TIM_CtrlPWMOutputs(TIM1, ENABLE); }
关于这个驱动设计,注意以下三个问题:
(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;
6.3 拓展阅读
ADC的外部输入阻抗只有50KΩ,大家测量时要特别注意。另外,这里重点推荐两篇提高ADC精度的文档,是ST官方做的,对于阻抗和精度问题做了详细说明,下载地址:http://forum.armfly.com/forum.php?mod=viewthread&tid=82543 。
6.4 总结
关于ADC的驱动就为大家讲解这么多,一定要实际操作配置下。如果需要ADC其它的配置方式,在我们论坛置顶帖STM32-V5的裸机例子基础篇里面下载即可:http://forum.armfly.com/forum.php?mod=viewthread&tid=1285 。
【安富莱二代示波器教程】第6章 示波器设计—双通道ADC驱动的更多相关文章
- 【安富莱二代示波器教程】第17章 附件B---功能扩展和改进方向
完整教程下载地址:http://forum.armfly.com/forum.php?mod=viewthread&tid=45785 第17章 附件B---功能扩展和改进方向 ...
- 【安富莱二代示波器教程】第16章 附件A---电阻屏触摸校准
第16章 附件A---电阻屏触摸校准 二代示波器的触摸校准比较简单,随时随地都可以做触摸校准,按下K1按键即可校准.有时候我们做触摸校准界面,需要在特定的界面才可以进入触摸校准状态,非常繁琐 ...
- 【安富莱二代示波器教程】第19章 附件E---参考资料
第19章 附件E---参考资料 DSP教程 http://forum.armfly.com/forum.php?mod=viewthread&tid=3886 . FreeRTOS教 ...
- 【安富莱二代示波器教程】第18章 附件C---波形拟合
完整教程下载地址:http://forum.armfly.com/forum.php?mod=viewthread&tid=45785 第18章 附件C---波形拟合 emWin5. ...
- 【安富莱TCPnet网络教程】HTTP通信实例
第41章 HTTP超文本传输协议基础知识 本章节为大家讲解HTTP(HyperText Transfer Protocol,超文本传输协议),从本章节开始,正式进入嵌入式Web的设计和学习. ...
- 【安富莱】V6,V5开发板用户手册,重在BSP驱动包设计方法,HAL库的框架学习,授人以渔(2019-11-04)
说明: 1.本教程重在BSP驱动包设计方法和HAL库的框架学习,并将HAL库里面的各种弯弯绕捋顺,从而方便我们的程序设计. 2.本次工程延续以往的代码风格,从底层BSP驱动包到应用代码,变量命名,文件 ...
- 【安富莱STM32H7教程】第1章 初学STM32H7的准备工作
完整教程下载地址:http://forum.armfly.com/forum.php?mod=viewthread&tid=86980 第1章 初学STM32H7的准备工作 俗话说万事开头 ...
- 【安富莱】RTX嵌入式操作系统教程发布,支持F103,F407和F429,含81个配套例程(2017-10-17)
前言说明:1. 首先感谢大家对我们安富莱电子一年来的支持,2016年我们会再接再厉推出更好的教程. 2. 估计也有网友会问RTX的优势在那里,针对这个问题,教程中第一章分为6条专门回答了这个问题,有兴 ...
- 【安富莱】【RL-TCPnet网络教程】第10章 RL-TCPnet网络协议栈移植(FreeRTOS)
第10章 RL-TCPnet网络协议栈移植(FreeRTOS) 本章教程为大家讲解RL-TCPnet网络协议栈的FreeRTOS操作系统移植方式,学习了第6章讲解的底层驱动接口函数之后,移植就 ...
随机推荐
- 处理H5新标签方法
语义化 HTML5中加入了更加具有语义化的标签,比如header,nav,footer等,可以为搜索引擎优化,让爬虫能更好地理解网页结构. 但是对于新标签的兼容性不是很好,IE9以下旧版本不支持新的语 ...
- 第一个 Python 程序
## 目标 * 第一个 `HelloPython` 程序* `Python 2.x` 与 `3.x` 版本简介* 执行 `Python` 程序的三种方式 * 解释器 —— `python` / ` ...
- 论文阅读笔记四十九:ScratchDet: Training Single-Shot Object Detectors from Scratch(CVPR2019)
论文原址:https://arxiv.org/abs/1810.08425 github:https://github.com/KimSoybean/ScratchDet 摘要 当前较为流行的检测算法 ...
- IDEA下运行 mybatis报错 Parameter 'arg0' not found. Available parameters are [autoRecharge, id, param1, param2]
电脑换系统之后重新安装一了 一下idea 项目运行时出现了以下错误, [autoRecharge, id, param1, param2] 或 [arg0, id, arg1, param2] 参考地 ...
- 网络安装Centos x64 6.10
1.下载老毛桃PE最新增强版本,然后生成一个可启动U盘. 2.在U盘或移动硬盘中创建一个目录 MYEXT,然后把centos的安装iso放到里面. 3.引导选择从外置ISO进行安装. https:// ...
- Redis数据类型Set
Redis的SET是无序的String集合,它里面的元素是不会重复的. SADD,SMEMBERS SADD命令会添加新元素到SET,可以看到一次性可以添加一个或多个元素.SMEMBERS可以获取se ...
- 如何在本地数据中心安装Service Fabric for Windows集群
概述 首先本文只是对官方文档(中文,英文)的一个提炼,详细的安装说明还请仔细阅读官方文档. 虽然Service Fabric的官方名称往往被加上Azure,但是实际上(估计很多人不知道)Service ...
- (六)read读取控制台输入
1.基本语法 read(选项)(参数) 选项: -p:指定读取值时的提示符: -t:指定读取值时等待的时间(秒). 参数 变量:指定读取值的变量名 2.案例实操 (1)提示7秒内,读取控制台输入的名称 ...
- caffe编译错误记录
1. caffe.pb.h丢失问题 错误代码如图: zhuoshi@zhuoshi-SYS-7048GR-TR:~/ZSZT/Geoffrey/caffe/caffe-master$ make all ...
- Java下载文件的几种方式
转发自博客园Sunny的文章 1.以流的方式下载 public HttpServletResponse download(String path, HttpServletResponse respon ...