交流,CP的PWM发波、检测的介绍
- CP电压的ADC模拟量采集
介绍:CP为充电桩的枪头电压,需要通过ADC来采集CP的电压变化来确定CP的电压值。ADC通过定时器2PWM的电平变化来触发ADC的采样,定时器的PWM变化是25us一次,1s内采集40个点。注意采样点要大于ADC的转换时间。
1.1 定时器2
1.1.1 定时器2的时基APB1-60Mhz,1个滴答为1us,周期25us。代码配置如下所示。
void Timer2Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
// TIM2 clock enable
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
// 自动重装载寄存器周期的值(计数值)
TIM_TimeBaseStructure.TIM_Period = (25 - 1);
// 累计 TIM_Period个频率后产生一个更新或者中断
// 这个就是预分频系数
TIM_TimeBaseStructure.TIM_Prescaler = (60 - 1);
// 采样分频
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
// 向上计数模式
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
// 初始化定时器2
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
// 清除溢出中断标志
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
// 溢出中断使能
//TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
/* Output Compare Timing Mode configuration: Channel1 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 10;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OC3Init(TIM2, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM2, ENABLE);
// 计数器使能
//TIM_Cmd(TIM2, ENABLE);
/* TIM Interrupts enable */
TIM_ITConfig(TIM2, TIM_IT_CC3|TIM_IT_Update, ENABLE);
/* Slave Mode selection: TIM2 */
TIM_SelectSlaveMode(TIM2,TIM_SlaveMode_Trigger);
TIM_SelectInputTrigger(TIM2,TIM_TS_ITR0);
/* Select the Master Slave Mode */
TIM_SelectMasterSlaveMode(TIM2,TIM_MasterSlaveMode_Disable);
TIM_SelectOutputTrigger(TIM2,TIM_TRGOSource_OC3Ref);
TIM_Cmd(TIM2, DISABLE);
//TIM_Cmd(TIM2, ENABLE);
}
1.2.ADC1/2
1.2.1 ADC1的最大输入时钟频率14Mhz。双通道同时采样并在DMA中断读取每次转换的结果,对两路信号进行ADC同时采样。由于一路信号将作为参考信号解调另一路信号,所以要确保两路信号的每次采样是同时进行的。所以,需要将ADC设置成“多重ADC模式”中的“规则同时模式”下的“双重ADC模式”(ADC_DualMode_RegSimult)。ADC的每次转换由定时器触发(ADC_ExternalTrigConvEdge_Rising)。
adc的配置
void BSP_ADC_Config(void)
{
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
/*ADC Clock config----------------------------------------------*/
RCC_APB2PeriphClockCmd( RCC_APB2Periph_ADC1|RCC_APB2Periph_ADC2, ENABLE);
/*ADC init------------------------------------------------------*/
ADC_DeInit();
/*ADC1,2 DMA config-----------------------------------------------*/
ADC12_DMA_Config(DMA2_Stream4,(u32)&ADC->CDR,(u32)&AD_DATA,NUM_AD12_CHANNEL);
/*ADC3 DMA config-----------------------------------------------*/
/* ADC Common config ------------------------------------------*/
ADC_CommonInitStructure.ADC_Mode = ADC_DualMode_RegSimult;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_2;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
ADC_CommonInit(&ADC_CommonInitStructure);
/* ADC1 configuration --------------------------------------------*/
ADC_StructInit(&ADC_InitStructure);
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising; //CP1 PWM
ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_T2_CC3;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //数据右对齐
ADC_InitStructure.ADC_NbrOfConversion = NUM_ADC1_CHANNEL;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 1, ADC_SampleTime_3Cycles); //PC0 ADC_SampleTime_13Cycles5
/* Enable ADC1 DMA */
ADC_DMACmd(ADC1, ENABLE);
/* ADC2 configuration ************************************/
ADC_StructInit(&ADC_InitStructure);
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; //CP2 PWM
ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_T2_CC3;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //数据右对齐
ADC_InitStructure.ADC_NbrOfConversion = NUM_ADC2_CHANNEL;
ADC_Init(ADC2, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC2, ADC_Channel_9, 1, ADC_SampleTime_3Cycles); //PC2
/* Enable DMA request after last transfer (multi-ADC mode) */
ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);
ADC_ITConfig(ADC1,ADC_IT_OVR,ENABLE);
ADC_ITConfig(ADC2,ADC_IT_OVR,ENABLE);
/* Enable ADC1,2,3 **************************************************************/
ADC_Cmd(ADC1, ENABLE);
ADC_Cmd(ADC2, ENABLE);
/* Enable ADC IT **************************************************************/
//over IT
//EOC IT
//ADC_ITConfig(ADC3,ADC_IT_EOC,ENABLE);
/* Start ADC1 Software Conversion */
}
DMA的配置如下。开启半输出中断及输出结束中断。
void ADC12_DMA_Config(DMA_Stream_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); //使能DMA时钟
DMA_InitTypeDef DMA_InitStructure;
DMA_StructInit(&DMA_InitStructure);
DMA_DeInit(DMA_CHx); //将DMA的通道1寄存器重设为缺省值
DMA_InitStructure.DMA_Channel = DMA_Channel_0;
DMA_InitStructure.DMA_PeripheralBaseAddr = cpar; //DMA外设基地址
DMA_InitStructure.DMA_Memory0BaseAddr = cmar; //DMA内存基地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; //数据传输方向,从外设发送到内存 DMA_CCRX位4
DMA_InitStructure.DMA_BufferSize = cndtr; //DMA通道的DMA缓存的大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器不变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器递增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; //外设数据宽度为16位
DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Word; //内存数据宽度为16位
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //工作在循环缓存模式
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; //DMA通道 x拥有高优先级
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(DMA_CHx, &DMA_InitStructure); //根据DMA_InitStruct中指定的参数初始化DMA的通道USART1_Tx_DMA_Channel所标识的寄存器
DMA_ClearITPendingBit(DMA_CHx,DMA_IT_HTIF4);
//DMA_ClearITPendingBit(DMA_CHx,DMA_IT_TCIF1);
DMA_ITConfig(DMA_CHx,DMA_IT_HT|DMA_IT_TC,ENABLE);
//DMA_ITConfig(DMA_CHx,DMA_IT_TC,ENABLE);
DMA_Cmd(DMA_CHx, ENABLE);//启动DMA通道
}
- 模拟量的处理
- 介绍
采集的CP模拟量需要进行数据定标、校准,
这里需要对CP的模拟量特别说下,正常CP采集到的点是40个点,但由于CP在发波时,是PWM的波形,所以仅对有效电平(高电平)进行滤波判断。如32A时,PWM的重载值533,周期为1000,53340/1000=21,去掉电平变化的3个点,对18个点求平均值。最后计算的值为CP的模拟量值。
数据定标:进行比例增益矫正。
AD采样值Va(0-4096)定标出CP值电压Vb(0-12V)。根据Vb=VaK1+B1公式,K1,B1为定标默认值。
数据校准:。
瞬时值:计算出来的值为瞬时值,CP电压的判断,工装的值均为瞬时值。
滤波值:进行滤波偏移。多用来进行工装、wifi后台显示。
- 介绍
- CP的PWM发波
3.1 介绍
CP的发波,通过定时器1来发波,滴答1us,周期1000,1ms,也就是国标要求的1Khz。
参考代码如下。
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
uint16_t PrescalerValue = 0;
TIM_OCStructInit(&TIM_OCInitStructure);
//120000000
PrescalerValue = (uint16_t) ((SystemCoreClock / 2) / 500000) - 1; //预分频系数
// TIM1 clock enable
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
//TIM_DeInit(TIM1);
// 自动重装载寄存器周期的值(计数值)
TIM_TimeBaseStructure.TIM_Period = (1000-1);
// 累计 TIM_Period个频率后产生一个更新或者中断
// 这个就是预分频系数
TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
// 采样分频
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
// 向上计数模式
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
// 初始化定时器1
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
// 清除溢出中断标志
TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
// 溢出中断使能
TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);
/* Output Compare Timing Mode configuration: Channel1 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 533;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
/* Output Compare Timing Mode configuration: Channel2 */
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 533;
TIM_OC2Init(TIM1, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM1, ENABLE);
//* TIM1 enable counter */
TIM_Cmd(TIM1, ENABLE);
/* TIM Interrupts enable */
TIM_ITConfig(TIM1, TIM_IT_CC1 | TIM_IT_CC2| TIM_IT_Update, ENABLE);
/* Select the Master Slave Mode */
TIM_SelectMasterSlaveMode(TIM1,TIM_MasterSlaveMode_Enable);
TIM_SelectOutputTrigger(TIM1,TIM_TRGOSource_OC1Ref);
TIM_CtrlPWMOutputs(TIM1, ENABLE);
注意,在发波使,使能pwm接口即可,如:使能:TIM_ForcedOC1Config(TIM1,TIM_OCMode_PWM1);
禁止:TIM_ForcedOC1Config(TIM1,TIM_ForcedAction_Active);