[STM32F1]

STM32基础篇——LCD PWM C DAC 实验

[复制链接]
1115|5
手机看帖
扫描二维码
随时随地手机跟帖
aizaixiyuanqian|  楼主 | 2018-1-28 12:16 | 显示全部楼层 |阅读模式
本帖最后由 aizaixiyuanqian 于 2018-1-28 12:53 编辑

上次试验,我们介绍了 STM32 自带 DAC 模块的使用, 但不是每个 STM32 都有 DAC 模块的,对于那些没有 DAC 模块的芯片,我们可以通过 PWM 来实现一个 PWM DAC。 本次试验我们将向大家介绍如何利用 STM32 的 PWM 来设计一个 DAC。我们将利用 STM32 的 TIM4 产生一个 PWM,通过 ADC1 的通道 8 采集 PWM 的输出电压, 并在 LCD 模块上面显示 ADC 获取到的电压值以及 PWM 的输出值等信息。本章分为以下学习目标:
1. 学会内部 DAC 的操作
aizaixiyuanqian|  楼主 | 2018-1-28 13:01 | 显示全部楼层
PWM-DAC  初始化
void pwm_dac_init()
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;//根据 TIM_OCInitStruct 中指定的参数初始化外设 TIMx
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
//设置该引脚为复用输出功能,输出 TIM4 CH1 的 PWM 脉冲波形
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
GPIO_Init(GPIOB,&GPIO_InitStructure);
//TIM4 定时器初始化
TIM_TimeBaseInitStructure.TIM_Period = 256;
TIM_TimeBaseInitStructure.TIM_Prescaler = 0;
TIM_TimeBaseInitStructure.TIM_ClockDivision = 0;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4, & TIM_TimeBaseInitStructure);
//  GPIO_PinRemapConfig(GPIO_FullRemap_TIM3,ENABLE);//改变指定管脚的映射
//pb5
//PWM 初始化  //根据 TIM_OCInitStruct 中指定的参数初始化外设 TIMx
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM2;
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//PWM 输出使能
TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;
TIM_OC1Init(TIM4,&TIM_OCInitStructure);
//注意此处初始化时 TIM_OC1Init 而不是 TIM_OCInit,否则会出错。因为固件库的版本不一样。
TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable);//使能或者失能 TIMx 在 CCR1上的预装载寄存器
TIM_ARRPreloadConfig(TIM4, ENABLE); //使能 TIMx 在 ARR 上的预装载寄存器
TIM_Cmd(TIM4,ENABLE);//使能或者失能 TIMx 外设
}

使用特权

评论回复
aizaixiyuanqian|  楼主 | 2018-1-28 13:04 | 显示全部楼层
ADC  初始化函数
void adc_init()
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO|RC
C_APB2Periph_ADC1,ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div6);//12M 最大 14M 设置 ADC 时钟
(ADCCLK)
ADC_DeInit(ADC1);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;//ADC //1
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN; //模拟输入
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure); //A
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
//设置指定 ADC 的规则组通道,设置它们的转化顺序和采样时间
ADC_RegularChannelConfig(ADC1,ADC_Channel_8,1,ADC_SampleTime_239Cycles
5); //1
//内部温度传感器是在 ADC1 通道 16 的。
//
ADC_RegularChannelConfig(ADC1,ADC_Channel_16,1,ADC_SampleTime_239Cycles5);
//  ADC_TempSensorVrefintCmd(ENABLE);//打开内部温度传感器使能
ADC_Cmd(ADC1,ENABLE);
ADC_ResetCalibration(ADC1);//重置指定的 ADC 的校准寄存器
while(ADC_GetResetCalibrationStatus(ADC1));//获取 ADC 重置校准寄存器的状态
ADC_StartCalibration(ADC1);//开始指定 ADC 的校准状态
while(ADC_GetCalibrationStatus(ADC1));//获取指定 ADC 的校准程序
ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能或者失能指定的 ADC 的软件转换启动功能
}

使用特权

评论回复
aizaixiyuanqian|  楼主 | 2018-1-28 13:10 | 显示全部楼层
//主程序
int main()
{
u16 value,value1,value2;
float ad;
u8 i=0,j,dat[7],dat1[7];
pwm_dac_init();
adc_init();
TFT_Init();  //TFT 彩屏初始化
LED_Init();  //端口初始化
printf_init();  //printf 初始化
TFT_ClearScreen(BLACK);  //清屏
GUI_Show12ASCII(10,10,"This is a PWM-DAC Check!",YELLOW,BLACK);
GUI_Show12ASCII(10,27,"Connect the PB6 PB0!",YELLOW,BLACK);
GUI_Show12ASCII(10,100,"The DA Value is:",YELLOW,BLACK);
GUI_Show12ASCII(10,117,"The AD Volage is:",YELLOW,BLACK);
while(1)
{
value=0;
for(i=0;i<=10;i++)
{
value=25*i;
TIM_SetCompare1(TIM4, value);//设置 TIMx 捕获比较 1 寄存器值
delay_ms(1);
value1=TIM_GetCapture1(TIM4);
dat[0]=value1/100+0x30;
dat[1]=value1%100/10+0x30;
dat[2]=value1%100%10+0x30;
dat[3]='\0';
ADC_SoftwareStartConvCmd(ADC1, ENABLE);  //使能或者失能指定的
ADC 的软件转换启动功能
while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));//转换结束标志位
value2=ADC_GetConversionValue(ADC1);
ad=value2*3.3/4096;
value2=ad*100;
dat1[0]=value2/100+0x30;
dat1[1]='.';
dat1[2]=value2%100/10+0x30;
dat1[3]=value2%100%10+0x30;
dat1[4]='V';
dat1[5]='\0';
GUI_Show12ASCII(160,100,dat,YELLOW,BLACK);
GUI_Show12ASCII(160,117,dat1,YELLOW,BLACK);
delay_ms(500);
if(j>1)
{
j=0;
GPIO_SetBits(GPIOC,GPIO_Pin_0);
}
else
{
j++;
GPIO_ResetBits(GPIOC,GPIO_Pin_0);
}
}
}
}

使用特权

评论回复
aizaixiyuanqian|  楼主 | 2018-1-28 13:10 | 显示全部楼层
主程序的效果是,通过 TIM4 产生一个 PWM 信号,将此信号接入到 ADC1 通道 8 中进行转换,将读取的电压值通过 LCD 进行显示,可以使用万用表测量 PB6 管脚的输出电压和LCD 上显示的电压值进行对比,整个过程运行 LED 闪烁。

使用特权

评论回复
aizaixiyuanqian|  楼主 | 2018-1-28 13:11 | 显示全部楼层
本次的试验是基于前几次试验例程作为基础,这次的也比较简单,作为以后开发产品经常使用。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

62

主题

1353

帖子

6

粉丝