ADC_ETC

备注:本文参考了恩智浦MCU加油站的”是什么让i.MX RT能完美支持多电机控制?“
3片74HC4052的输出连接ADC,分别连接ADC2_0,ADC2_1,ADC2_2,ADC2_3,ADC1_10,ADC1_12。共用切换信号,切换后ADC1和ADC2要同时启动转换,等ADC1和ADC2都转换完成再启动下次转换。

1、结构图
在这里插入图片描述

在这里插入图片描述

► 有8组采样控制队列(Queue),每个Queue通过配置可以有0~8个Chain。也就是说,整个ADC_ETC最多有64个Chain。

► Queue 0/1/2/3 只能操控ADC1,Queue 4/5/6/7只能操控ADC2。

► 每个Chain都可以操控ADC对任意一通道完成1次采样、保存1个采样结果,在采样完成后也可以选择是否使能DONE0/DONE1/DONE2这3个中断中的任意一个。

► 每个Queue对应1个触发输入(Trigger IN)。每次Trigger IN信号到来后,对应的Queue将从Chain0开始按顺序连续执行所有的Chains,每个Chain之间可以预设间隔时间。

► 每个Trigger IN都可以通过XBAR链接到PWM的触发信号,且Trigger IN之间可以共用同一个触发源。

► 可配置Trigger IN/Queue的优先级,一共8个优先级。如果操控同一个ADC的Trigger IN/Queue同时被触发,则先执行优先级高的,再执行优先级低的。
► 异步模式(AsyncMode):

Queue0/1/2/3分别由TRIG0/1/2/3触发,Queue4/5/6/7分别由TRIG4/5/6/7触发。

► 同步模式(SyncMode):

Queue0/4,Queue1/5,Queue2/6,Queue3/7分别由TRIG0/1/2/3同时触发。显然,利用同步模式,可以方便地ADC1,ADC2同步并行采样。
值得注意的是,在配置ADC_ETC初始化代码时,一定要先按下面的步骤顺序配置ADC_ETC全局控制寄存器(Global Control Register 如图3),之后才能操作ADC_ETC的其他寄存器。
① 单独清零SOFTRST位,否则对其他寄存器的操作将无效。

ADC_ETC->CTRL &= ~ADC_ETC_CTRL_SOFTRST_MASK;

② 如果想使用ADC2,则需要清零TSC_BYPASS位,否则ADC2将被TSC占用。

ADC_ETC->CTRL &= ~ADC_ETC_CTRL_TSC_BYPASS_MASK;

2、配置ADC_ETC Global Control Register,在SDK中通过adc_etc_config_t结构体,ADC_ETC_Init函数来设置。

3、配置ETC_TRIGX Control Register,在SDK中通过adc_etc_trigger_config_t结构体,ADC_ETC_SetTriggerConfig函数来设置。

4、配置ETC_TRIG Chain x Register,在SDK中通过adc_etc_trigger_config_t结构体,ADC_ETC_SetTriggerChainConfig函数来设置。

5、XBARA_SetSignalsConnection()用于连接输入和输出信号。

#include "stm32f10x.h" #include "stm32f10x_adc.h" #include "stm32f10x_tim.h" #include "stm32f10x_gpio.h" #include "stm32f10x_rcc.h" #include "math.h" // PID参数结构体 typedef struct { float Kp; float Ki; float Kd; float integral_limit; float output_limit; float integral; float prev_error; } PID_Controller; // 系统参数 #define PWM_PERIOD 999 // PWM周期 (ARR值) #define V_REF 24.0f // 目标输出电压 (24V) #define MAX_DUTY 0.85f // 最大占空比限制 #define MIN_DUTY 0.05f // 最小占空比限制 // ADC采样值 volatile uint16_t adc_voltage = 0; // 输出电压采样 volatile uint16_t adc_current = 0; // 电感电流采样 // PID控制器实例 PID_Controller voltage_pid = {0.5, 0.01, 0.0, 100.0, 5.0, 0, 0}; // 电压环PID PID_Controller current_pid = {0.8, 0.05, 0.01, 50.0, 3.0, 0, 0}; // 电流环PID // 函数声明 void GPIO_Configuration(void); void ADC_Configuration(void); void TIM_Configuration(void); void NVIC_Configuration(void); void PID_Init(PID_Controller *pid, float kp, float ki, float kd, float int_limit, float out_limit); float PID_Update(PID_Controller *pid, float setpoint, float measurement); float Map_ADC_To_Voltage(uint16_t adc_value); float Map_ADC_To_Current(uint16_t adc_value); int main(void) { // 系统初始化 SystemInit(); GPIO_Configuration(); ADC_Configuration(); TIM_Configuration(); NVIC_Configuration(); // PID初始化 PID_Init(&voltage_pid, voltage_pid.Kp, voltage_pid.Ki, voltage_pid.Kd, voltage_pid.integral_limit, voltage_pid.output_limit); PID_Init(&current_pid, current_pid.Kp, current_pid.Ki, current_pid.Kd, current_pid.integral_limit, current_pid.output_limit); // 启动ADC和定时器 ADC_SoftwareStartConvCmd(ADC1, ENABLE); TIM_Cmd(TIM1, ENABLE); TIM_CtrlPWMOutputs(TIM1, ENABLE); while (1) { // 主循环中可添加监控或通信功能 // 控制算法在定时器中断中执行 } } // PID初始化函数 void PID_Init(PID_Controller *pid, float kp, float ki, float kd, float int_limit, float out_limit) { pid->Kp = kp; pid->Ki = ki; pid->Kd = kd; pid->integral_limit = int_limit; pid->output_limit = out_limit; pid->integral = 0; pid->prev_error = 0; } // PID更新函数 float PID_Update(PID_Controller *pid, float setpoint, float measurement) { float error = setpoint - measurement; // 积分项更新 pid->integral += error; // 积分限幅 if (pid->integral > pid->integral_limit) pid->integral = pid->integral_limit; if (pid->integral < -pid->integral_limit) pid->integral = -pid->integral_limit; // 微分项计算 float derivative = error - pid->prev_error; pid->prev_error = error; // PID输出 float output = pid->Kp * error + pid->Ki * pid->integral + pid->Kd * derivative; // 输出限幅 if (output > pid->output_limit) output = pid->output_limit; if (output < -pid->output_limit) output = -pid->output_limit; return output; } // 电压ADC值转实际电压 (假设12位ADC, 分压比10:1, 参考电压3.3V) float Map_ADC_To_Voltage(uint16_t adc_value) { return (adc_value * 3.3f / 4096) * 11.0f; // 分压比计算 } // 电流ADC值转实际电流 (假设采样电阻0.1Ω, 放大倍数20) float Map_ADC_To_Current(uint16_t adc_value) { return (adc_value * 3.3f / 4096) / 0.1f / 20.0f; } // 定时器3中断服务函数 (控制周期) void TIM3_IRQHandler(void) { if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) { // 读取ADC值 float output_voltage = Map_ADC_To_Voltage(adc_voltage); float inductor_current = Map_ADC_To_Current(adc_current); // 电压外环计算电流参考 float current_ref = PID_Update(&voltage_pid, V_REF, output_voltage); // 电流内环计算占空比 float duty_cycle = PID_Update(&current_pid, current_ref, inductor_current); // 占空比限幅 if (duty_cycle > MAX_DUTY) duty_cycle = MAX_DUTY; if (duty_cycle < MIN_DUTY) duty_cycle = MIN_DUTY; // 更新PWM占空比 TIM_SetCompare1(TIM1, (uint16_t)(duty_cycle * PWM_PERIOD)); TIM_ClearITPendingBit(TIM3, TIM_IT_Update); } } // ADC中断服务函数 void ADC1_2_IRQHandler(void) { if (ADC_GetITStatus(ADC1, ADC_IT_JEOC) == SET) { // 读取注入通道采样值 adc_voltage = ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_1); adc_current = ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_2); ADC_ClearITPendingBit(ADC1, ADC_IT_JEOC); } } // 外设配置函数 void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; // PWM输出引脚 (TIM1 CH1 - PA8) RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // ADC输入引脚 (电压采样 - PA1, 电流采样 - PA2) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOA, &GPIO_InitStructure); } void TIM_Configuration(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; // PWM定时器配置 (TIM1 - 20kHz) RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); TIM_TimeBaseStructure.TIM_Period = PWM_PERIOD; TIM_TimeBaseStructure.TIM_Prescaler = SystemCoreClock / 20000000 - 1; // 72MHz->20kHz TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); // PWM通道配置 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 0; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC1Init(TIM1, &TIM_OCInitStructure); // 控制周期定时器 (TIM3 - 10kHz) RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); TIM_TimeBaseStructure.TIM_Period = SystemCoreClock / 10000 - 1; // 10kHz TIM_TimeBaseStructure.TIM_Prescaler = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); TIM_Cmd(TIM3, ENABLE); } void ADC_Configuration(void) { ADC_InitTypeDef ADC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); // ADC基本配置 ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode = ENABLE; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel = 2; ADC_Init(ADC1, &ADC_InitStructure); // 配置注入通道 (电压:通道1, 电流:通道2) ADC_InjectedSequencerLengthConfig(ADC1, 2); ADC_InjectedChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_28Cycles5); ADC_InjectedChannelConfig(ADC1, ADC_Channel_2, 2, ADC_SampleTime_28Cycles5); // 使能注入通道转换结束中断 ADC_ITConfig(ADC1, ADC_IT_JEOC, ENABLE); // 定时器触发ADC采样 (TIM3触发) ADC_ExternalTrigInjectedConvConfig(ADC1, ADC_ExternalTrigInjecConv_T3_TRGO); ADC_Cmd(ADC1, ENABLE); // ADC校准 ADC_ResetCalibration(ADC1); while(ADC_GetResetCalibrationStatus(ADC1)); ADC_StartCalibration(ADC1); while(ADC_GetCalibrationStatus(ADC1)); } void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; // 配置ADC中断 NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); // 配置TIM3中断 NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_Init(&NVIC_InitStructure); } 第 218 行提示 error: use of undeclared identifier 'ADC ExternalTrigInjecConv T3 TRGO 改掉错误,然后给我完整代码
07-25
..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_SoftwareStartConv multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol __asm___15_stm32f4xx_adc_c_e11a2ea2____REV16 multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol __asm___15_stm32f4xx_adc_c_e11a2ea2____REVSH multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_DeInit multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_Init multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_StructInit multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_CommonInit multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_CommonStructInit multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_Cmd multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_AnalogWatchdogCmd multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_AnalogWatchdogThresholdsConfig multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_AnalogWatchdogSingleChannelConfig multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_TempSensorVrefintCmd multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_VBATCmd multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_RegularChannelConfig multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_GetSoftwareStartConvStatus multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_EOCOnEachRegularChannelCmd multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_ContinuousModeCmd multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_DiscModeChannelCountConfig multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_DiscModeCmd multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_GetConversionValue multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_GetMultiModeConversionValue multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_DMACmd multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_DMARequestAfterLastTransferCmd multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_MultiModeDMARequestAfterLastTransferCmd multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_InjectedChannelConfig multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_InjectedSequencerLengthConfig multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_SetInjectedOffset multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_ExternalTrigInjectedConvConfig multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_ExternalTrigInjectedConvEdgeConfig multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_SoftwareStartInjectedConv multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_GetSoftwareStartInjectedConvCmdStatus multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_AutoInjectedConvCmd multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_InjectedDiscModeCmd multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_GetInjectedConversionValue multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_ITConfig multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_GetFlagStatus multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_ClearFlag multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_GetITStatus multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). ..\OBJ\ADC.axf: Error: L6200E: Symbol ADC_ClearITPendingBit multiply defined (by stm32f4xx_adc_2.o and stm32f4xx_adc.o). Not enough information to list image symbols. Not enough information to list the image map.
10-30
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值