|
刚从51转过来,不想投入太多的资金,选择某宝的小蓝板(bluePill),这个板可能是最便宜的了(7.6元包邮)。初步测试一下时钟,定时器,中断,DMA什么的。到ADC还比较满意,DAC就晕了(这个芯片没有DAC)。于是采用PWM出模拟值。先初始化; void TIM1_PWM_Init(u16 arr,u16 psc) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); // RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); //使能GPIO外设时钟使能 //设置该引脚为复用输出功能,输出TIM1 CH1的PWM脉冲波形 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //TIM_CH1 //PA8是PWM输出 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); //定时器初始化 TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式 TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位 //初始化输出比较参数 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能 TIM_OCInitStructure.TIM_Pulse = 1350; //设置待装入捕获比较寄存器的脉冲值 1350--Low 200--High TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性:TIM输出比较极性高 TIM_OC1Init(TIM1, &TIM_OCInitStructure); //根据TIM_OCInitStruct中指定的参数初始化外设TIMx //使能预装载寄存器 TIM_CtrlPWMOutputs(TIM1,ENABLE); //MOE 主输出使能。该函数操作的是TIM1 刹车和死区寄存器该函数并不是适合所有定时器的, //只有部分定时器可以使用,例如,在stm32f0中,可用于TIM1, TIM15, TIM16以及TIM17, //在stm32f1中可用于TIM1, TIM8,TIM15, TIM16以及TIM17,如果在其它定时器中使用, //可能会使STM32停留在某一处而无法继续执行下面的任务 TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable); //CH1预装载使能 TIM_ARRPreloadConfig(TIM1, ENABLE); //使能TIMx在ARR上的预装载寄存器 TIM_Cmd(TIM1,ENABLE); //使能TIM1 } 然后在MAIN()中: int main() { TIM_SetCompare1(TIM1,1500); //占空比=1000 / (2999+1)*100% = 50% while(1) { ; } } 可以在PA8看到PWM波形。一顿操作:
发现DAC输出精度,线性都不好。也不知道是运放的问题还是其他。网上一顿搂,改进PWM输出模拟量。
效果好了不少。线性还是不好。 于是将DAC又返回ADC采集加数字闭环。 dac_d是期望输出的值,dac_out是送去PWM转换的值,vi是从DACOUT那里取出的电压ADC值。下面程序是数字反馈 void dac_auto(void) { u16 tmp; if((short int)vi>(dac_d+1)) { tmp=(short int)vi-dac_d; if(tmp>=220)dac_out-=170; else if(tmp>=100)dac_out-=80; else if(tmp>=50)dac_out-=45; else if(tmp>=10)dac_out-=6; else if(tmp>=5)dac_out-=2; else dac_out-=1; } else if((short int)vi<(dac_d-1)) { tmp=dac_d-(short int)vi; if(tmp>=220)dac_out+=110; else if(tmp>=100)dac_out+=55; else if(tmp>=50)dac_out+=35; else if(tmp>=10)dac_out+=7; else if(tmp>=5)dac_out+=3; else dac_out+=1; } if(dac_out>=2999)dac_out=2999; if(dac_out<=1)dac_out=1; TIM_SetCompare1(TIM1,dac_out); filter(); } 经过处理,PWM输出的最终电压值波动小于1毫伏。 |
微信公众号
手机版