完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
2个回答
|
|
一、ADC,模拟数字转换器
1、定义 ADC(Analog to Digital Converter) :模数变换器;简称“模数转换器”,把模拟量转换为数字量的装置。 在计算机控制系统中,须经各种检测装置,以连续变化的电压或电流作为模拟量,随时提供被控制对象的有关参数(如速度、压力、温度等)而进行控制。计算机的输入必须是数字量,故需用模数转换器达到控制目的,过程有抽样、量化、编码(PCM编码,脉冲编码调制)。 其次简单介绍一下PCM编码: (1)抽样:就是对模拟信号进行周期性扫描,把时间上连续的信号变成时间上离散的信号。该模拟信号经过抽样后述应当包含原信号中所有信息,也就是说能无失真的恢复原模拟信号。 (2)量化:就是把经过抽样得到的瞬时值将其幅度离散,即用一组规定的电平,把瞬时抽样值用最接近的电平值来表示,通常是用二进制表示。 (3)编码:就是用一组二进制码组来表示每一个有固定电平的量化值。然而,实际上量化是在编码过程中同时完成的,故编码过程也称为模/数变换,可记作A/D。 2、模拟信号 模拟信号是指用连续变化的物理量表示的信息,其信号的幅度,或频率,或相位随时间作连续变化,如目前广播的声音信号,或图像信号等。抓重点,连续的,如正弦波。 3、数字信号 数字信号指幅度的取值是离散的,幅值表示被限制在有限个数值之内。 二进制码就是一种数字信号。二进制码受噪声的影响小,易于有数字电路进行处理,所以得到了广泛的应用。抓重点,离散的,但在示波器中的方波一般指的是数字信号,把竖线去掉就是离散的了。 4、常用库函数 a.根据ADC_CommonInitTypeDef结构体,初始化ADC外设指定的参数(容易被忽略) typedef struct { uint32_t ADC_Mode; /*!《 Configures the ADC to operate in independent or multi mode. This parameter can be a value of @ref ADC_Common_mode */ uint32_t ADC_Prescaler; /*!《 Select the frequency of the clock to the ADC. The clock is common for all the ADCs. This parameter can be a value of @ref ADC_Prescaler */ uint32_t ADC_DMAAccessMode; /*!《 Configures the Direct memory access mode for multi ADC mode. This parameter can be a value of @ref ADC_Direct_memory_access_mode_for_multi_mode */ uint32_t ADC_TwoSamplingDelay; /*!《 Configures the Delay between 2 sampling phases. This parameter can be a value of @ref ADC_delay_between_2_sampling_phases */ }ADC_CommonInitTypeDef; @param ADC_CommonInitStruct: pointer to an ADC_CommonInitTypeDef structure that contains the configuration information for All ADCs peripherals. void ADC_CommonInit(ADC_CommonInitTypeDef* ADC_CommonInitStruct) b.根据ADC_InitTypeDef结构体,初始化ADC外设指定的参数 typedef struct { uint32_t ADC_Resolution; /*!《 Configures the ADC resolution dual mode. This parameter can be a value of @ref ADC_resolution */ FunctionalState ADC_ScanConvMode; /*!《 Specifies whether the conversion is performed in Scan (multichannels) or Single (one channel) mode. This parameter can be set to ENABLE or DISABLE */ FunctionalState ADC_ContinuousConvMode; /*!《 Specifies whether the conversion is performed in Continuous or Single mode. This parameter can be set to ENABLE or DISABLE. */ uint32_t ADC_ExternalTrigConvEdge; /*!《 Select the external trigger edge and enable the trigger of a regular group. This parameter can be a value of @ref ADC_external_trigger_edge_for_regular_channels_conversion */ uint32_t ADC_ExternalTrigConv; /*!《 Select the external event used to trigger the start of conversion of a regular group. This parameter can be a value of @ref ADC_extrenal_trigger_sources_for_regular_channels_conversion */ uint32_t ADC_DataAlign; /*!《 Specifies whether the ADC data alignment is left or right. This parameter can be a value of @ref ADC_data_align */ uint8_t ADC_NbrOfConversion; /*!《 Specifies the number of ADC conversions that will be done using the sequencer for regular channel group. This parameter must range from 1 to 16. */ }ADC_InitTypeDef; @brief Initializes the ADCx peripheral according to the specified parameters in the ADC_InitStruct. @note This function is used to configure the global features of the ADC ( Resolution and Data Alignment), however, the rest of the configuration parameters are specific to the regular channels group (scan mode activation, continuous mode activation, External trigger source and edge, number of conversion in the regular channels group sequencer)。 @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. @param ADC_InitStruct: pointer to an ADC_InitTypeDef structure that contains the configuration information for the specified ADC peripheral. void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct) c.为选定的ADC常规通道进行配置 @brief Configures for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. @param ADC_Channel: the ADC channel to configure. This parameter can be one of the following values: @arg ADC_Channel_0~~~~~~arg ADC_Channel_18 @param Rank: The rank in the regular group sequencer. This parameter must be between 1 to 16. @param ADC_SampleTime: The sample time value to be set for the selected channel. This parameter can be one of the following values: @arg ADC_SampleTime_3Cycles: Sample time equal to 3 cycles @arg ADC_SampleTime_15Cycles: Sample time equal to 15 cycles @arg ADC_SampleTime_28Cycles: Sample time equal to 28 cycles @arg ADC_SampleTime_56Cycles: Sample time equal to 56 cycles @arg ADC_SampleTime_84Cycles: Sample time equal to 84 cycles @arg ADC_SampleTime_112Cycles: Sample time equal to 112 cycles @arg ADC_SampleTime_144Cycles: Sample time equal to 144 cycles @arg ADC_SampleTime_480Cycles: Sample time equal to 480 cycles void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime) 例如是42MHZ,3cycle采集一次,那么时间就是3*1/42Mhz=0.07us,即三个ADC时钟的时间 d.使能指定的ADC的软件转换启动功能 @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. void ADC_SoftwareStartConv(ADC_TypeDef* ADCx) e.检查指定的ADC标志是否已设置 @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. @param ADC_FLAG: specifies the flag to check. This parameter can be one of the following values: @arg ADC_FLAG_AWD: Analog watchdog flag @arg ADC_FLAG_EOC: End of conversion flag(结束标志位) @arg ADC_FLAG_JEOC: End of injected group conversion flag @arg ADC_FLAG_JSTRT: Start of injected group conversion flag @arg ADC_FLAG_STRT: Start of regular group conversion flag @arg ADC_FLAG_OVR: Overrun flag @retval The new state of ADC_FLAG (SET or RESET)。 FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG) 具体的函数在固件库手册找不到的时候,可以在对应的stm32f4xx_adc.c中查找,function列表的函数 f.返回ADC对应通道的测量数据 @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral. @retval The Data conversion value. uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx) g.左对齐和右对齐 4、STM32F4的ADC最高分辨率是12位,即最大数值达到4095, 12位分辨率最低可以测量:3300mV/4095=0.8mV 10位分辨率最低可以测量:3300mV/1024=3.22mV 所以分辨率越高,精度越高。 5、测量结果转换为电压值 被测量电压 = ADC对应通道的测量数据 * 参考电压 /4095. 一般参考电压为3.3V,用3300mV来计算,主要由自己决定。 正常输出电压的例子: ADC硬件的时钟记得开启(易漏点) #include “stm32f4xx.h” #include “stm32f4xx_gpio.h” #include “stm32f4xx_rcc.h” #include “stm32f4xx_usart.h” #include “stdio.h” #include “sys.h” static GPIO_InitTypeDef GPIO_InitStructure; static USART_InitTypeDef USART_InitStructure; static NVIC_InitTypeDef NVIC_InitStructure; static ADC_InitTypeDef ADC_InitStructure; static ADC_CommonInitTypeDef ADC_CommonInitStructure; //重定义fputc函数 int fputc(int ch, FILE *f) { USART_SendData(USART1,ch); while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET); return ch; } void delay_us(uint32_t nus) { uint32_t temp; SysTick-》LOAD =SystemCoreClock/8/1000000*nus; //时间加载 SysTick-》VAL =0x00; //清空计数器 SysTick-》CTRL|=SysTick_CTRL_ENABLE_Msk ; //使能滴答定时器开始倒数 do { temp=SysTick-》CTRL; }while((temp&0x01)&&!(temp&(1《《16))); //等待时间到达 SysTick-》CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器 SysTick-》VAL =0X00; //清空计数器 } void delay_ms(uint16_t nms) { uint32_t temp; SysTick-》LOAD=SystemCoreClock/8/1000*nms; //时间加载(SysTick-》LOAD为24bit) SysTick-》VAL =0x00; //清空计数器 SysTick-》CTRL|=SysTick_CTRL_ENABLE_Msk ; //能滴答定时器开始倒数 do { temp=SysTick-》CTRL; }while((temp&0x01)&&!(temp&(1《《16))); //等待时间到达 SysTick-》CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器 SysTick-》VAL =0X00; //清空计数器 } void USART1_Init(uint32_t baud) { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); //使能USART1时钟 //串口1对应引脚复用映射 GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIOA9复用为USART1 GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10复用为USART1 //USART1端口配置 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9与GPIOA10 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉 GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9,PA10 //USART1 初始化设置 USART_InitStructure.USART_BaudRate = baud; //波特率设置 USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长为8位数据格式 USART_InitStructure.USART_StopBits = USART_StopBits_1; //一个停止位 USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验位 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件数据流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式 USART_Init(USART1, &USART_InitStructure); //初始化串口1 USART_Cmd(USART1, ENABLE); //使能串口1 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启相关中断 //Usart1 NVIC 配置 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //串口1中断通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3; //抢占优先级3 NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器 } void adc_init(void) { //使能GPIOA的硬件时钟 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //使能ADC1硬件时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); /* 配置ADC1通道5为模拟输入引脚 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //引脚设置为模拟输入,能够识别更加广范围的电平(0V~3.3V任何电压) GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; GPIO_Init(GPIOA, &GPIO_InitStructure); |
|
|
|
ADC常规的初始化
/*独立模式,在当前的通道5只采用1个ADC硬件进行工作*/ ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; //ADC硬件的工作时钟= APB2(84MHz)/2=42MHz ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; //禁止DMA //ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; //如果采用多个ADC对某一个通道进行采样的时候,才需要设置 ADC_CommonInit(&ADC_CommonInitStructure); ADC1初始化 /*12位分辨率*/ ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; //因没有使用DMA,则不需要使用自动扫描模式。当前使用软件触发一次,则扫描一次 ADC_InitStructure.ADC_ScanConvMode = DISABLE; //模拟数字转换器一直工作 ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //禁止触发检测,不需要外部引脚电平识别来让ADC硬件工作 ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; //右对齐 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //执行一次转换结果 ADC_InitStructure.ADC_NbrOfConversion = 1; ADC_Init(ADC1, &ADC_InitStructure); /* 指定ADC1常规通道5的采样时间,采样时间=3个ADC时钟时间,这是最短的时间*/ ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 1, ADC_SampleTime_3Cycles); /* Enable ADC1 */ ADC_Cmd(ADC1, ENABLE); } int main(void) { uint32_t adc_val,adc_vol; //系统定时器初始化,时钟源来自HCLK,且进行8分频, //系统定时器时钟频率=168MHz/8=21MHz SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //设置中断优先级分组2 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //串口1,波特率115200bps,开启接收中断 USART1_Init(115200); //ADC初始化 adc_init(); while(1) { /* 1---启动ADC1进行转换*/ ADC_SoftwareStartConv(ADC1); /*2---等待转换结束,结束时标志位置1,1!=0,跳出循环*/ while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==RESET); /*3---获取ADC转换后的数值*/ adc_val=ADC_GetConversionValue(ADC1); //将ADC输出的结果值转换位电压值,打印 adc_vol = adc_val*3300/4095; printf(“vol = %dmvrn”,adc_vol); delay_ms(500); } } //串口1中断服务程序 void USART1_IRQHandler(void) { uint8_t d; if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断 { d = USART_ReceiveData(USART1); } } #后续练习 调整可调电阻以控制LED灯的亮度,ADC获取电压值,根据电压值实现PWM占空比。 部分代码: void tim14_init(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; /* GPIOF clock enable */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); /* GPIOF Configuration: TIM14 CH1 (PF9) */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能,使用引脚的第二功能 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ; GPIO_Init(GPIOF, &GPIO_InitStructure); /* Connect TIM pins to AF9 */ GPIO_PinAFConfig(GPIOF, GPIO_PinSource9, GPIO_AF_TIM14); /* TIM14 clock enable */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14, ENABLE); /* Time base configuration,100Hz*/ TIM_TimeBaseStructure.TIM_Period = (10000/100)-1; //定时计数值,100Hz TIM_TimeBaseStructure.TIM_Prescaler = 8400; //预分频值 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //再次进行1分频 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数 TIM_TimeBaseInit(TIM14, &TIM_TimeBaseStructure); /* PWM1 Mode configuration: Channel1 */ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC1Init(TIM14, &TIM_OCInitStructure); TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable); //自动重载初值,不断输出PWM脉冲 TIM_ARRPreloadConfig(TIM14, ENABLE); //自动重载使能 /* TIM14 enable counter */ TIM_Cmd(TIM14, ENABLE); } int main(void) { uint32_t adc_val,adc_vol,pwm_cmp=0;; //系统时钟的时钟源=168MHz/8=21MHz SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //串口初始化,波特率为115200bps usart1_init(115200); //adc初始化,12位精度 adc_init(); //定时器14初始化为PWM,使用PWM通道1,当前频率为100Hz tim14_init(); while(1) { /* Start ADC Software Conversion ,启动ADC*/ ADC_SoftwareStartConv(ADC1); //等待转换结束 while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==RESET); //获取ADC转换后的数值 adc_val=ADC_GetConversionValue(ADC1); //将ADC的数值转换为电压值 adc_vol = adc_val *3300/4095; printf(“vol=%dmvrn”,adc_vol); //设置比较值 pwm_cmp = (adc_vol/3300)*100 ;//占用当前比例是多少,所以要乘100 TIM_SetCompare1(TIM14,pwm_cmp); printf(“pwm compare=%drn”,pwm_cmp); delay_ms(500); } } void USART1_IRQHandler(void) { uint8_t d; /* USART in Receiver mode */ if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET) { d= USART_ReceiveData(USART1); USART_SendData(USART1, d); /* Loop until the end of transmission ,直到串口数据帧全部发送完毕*/ while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET); } } |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1907 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1678 浏览 1 评论
1171 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
770 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1730 浏览 2 评论
1970浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
806浏览 4评论
stm32f4下spi+dma读取数据不对是什么原因导致的?
253浏览 3评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
623浏览 3评论
634浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-23 03:47 , Processed in 0.573377 second(s), Total 46, Slave 41 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号