蓝桥杯嵌入式十一届省题
一、分析
这一届的蓝桥杯嵌入式的省题相对来说还是比较简单的,其中主要的难点也就是对于adc和两路固定频率可调占空比pwm的配置,把这两个解决了,main函数编写起来相对往届简单。
这里题目主要涉及pwm、adc、key、led。
对于pwm的配置我这里主要用到定时器的输出比较翻转模式TIM_OCMode_Toggle来进行处理,并且用到中断服务函数处理。
对于adc的配置,也都是比较基本的了,就不多说了。
1.main函数
#include "stm32f10x.h"
#include "stdio.h"
#include "pwm.h"
#include "key.h"
#include "led.h"
#include "adc.h"
#include "lcd.h"
u32 TimingDelay = 0;
extern float ch1;
extern float ch2;
float ch1_f;
float ch2_f;
unsigned char key_val;
unsigned char chu_chun[40];
unsigned int adc_val;
unsigned char B1=0; //界面切换
unsigned char mode=0; //模式切换
unsigned char pa6_a=10;
unsigned char pa7_a=10;
void lcd_caozuo(void)
{
if(B1==0)
{
LCD_DisplayStringLine(Line3," Date ");
adc_val=adc_scanf();
sprintf((char *)chu_chun," V:%4.2f V ",(float)adc_val*3.3/4095);
LCD_DisplayStringLine(Line5,chu_chun);
if(mode==0)
{
LCD_DisplayStringLine(Line7," Mode:AUTO ");
ch1_f=((float)adc_val*3.3/4095)/3.3;
ch1=ch1_f;
ch2=ch1_f;
}
if(mode==1)
LCD_DisplayStringLine(Line7," Mode:MANU ");
else if(B1==1)
{
LCD_DisplayStringLine(Line3," Pare ");
sprintf((char *)chu_chun," PA6:%2u%% ",pa6_a);
LCD_DisplayStringLine(Line5,chu_chun);
sprintf((char *)chu_chun," PA7:%2u%% ",pa7_a);
LCD_DisplayStringLine(Line7,chu_chun);
}
}
void key_caozuo(void)
{
key_val=key_scanf(); //读取按键值
if(key_val==1)
{
switch(B1)
{
case 0:B1=1;break;
case 1:B1=0;break;
}
}
if(key_val==2)
{
if(B1==1)
{
if(mode==1)
{
if(pa6_a!=100)
{
ch1=ch1+0.1;
pa6_a=pa6_a+10;
}
if(pa6_a==100)
{
ch1=0.1;
pa6_a=10;
}
}
}
}
if(key_val==3)
{
if(B1==1)
{
if(mode==1)
{
if(pa7_a!=100)
{
ch2=ch2+0.1;
pa7_a=pa7_a+10;
}
if(pa7_a==100)
{
ch1=0.1;
pa7_a=10;
}
}
}
}
if(key_val==4)
{
switch(mode)
{
case 0:mode=1;break;
case 1:mode=0;break;
}
}
}
//Main Body
int main(void)
{
SysTick_Config(72000);
STM3210B_LCD_Init();
LCD_Clear(Black);
LCD_SetBackColor(Black);
LCD_SetTextColor(White);
pwm_init();
key_init();
led_init();
adc_init();
while(1)
{
lcd_caozuo();
key_caozuo();
}
}
void SysTick_Handler(void)
{
led_init();
if(mode==0)
led_scanf(0,led1);
else if(mode==1)
led_scanf(1,led1);
if(B1==0)
led_scanf(0,led2);
else if(B1==1)
led_scanf(1,led2);
}
2.pwm
#include "pwm.h"
u16 CR2_val=10000; //100hz 72Mhz/72/10000
u16 CR1_val=5000; //200hz 72Mhz/72/5000
float ch1=0.1; //占空比
float ch2=0.1;
u16 cata;
_Bool pa6=0; //标志位
_Bool pa7=0;
void pwm_init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
TIM_OCInitTypeDef TIM_OCInitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
TIM_TimeBaseInitStruct.TIM_ClockDivision=0;
TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_Period=65535; //65536-1
TIM_TimeBaseInitStruct.TIM_Prescaler=71; //72mhz,¼ÆÊýƵÂÊΪ1mhz
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);
NVIC_InitStruct.NVIC_IRQChannel=TIM3_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority=0;
NVIC_Init(&NVIC_InitStruct);
TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_Toggle; //输出比较翻转
TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;
TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;
TIM_OCInitStruct.TIM_Pulse=CR1_val;
TIM_OC1Init(TIM3,&TIM_OCInitStruct);
TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Disable);
TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_Toggle;
TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;
TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;
TIM_OCInitStruct.TIM_Pulse=CR2_val;
TIM_OC2Init(TIM3,&TIM_OCInitStruct);
TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Disable);
TIM_Cmd(TIM3,ENABLE);
TIM_ITConfig(TIM3,TIM_IT_CC1|TIM_IT_CC2,ENABLE);
}
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3,TIM_IT_CC1)!=RESET)
{
TIM_ClearITPendingBit(TIM3,TIM_IT_CC1);
cata=TIM_GetCapture1(TIM3); //获取当前计数器的值
if(pa6==0)
{
TIM_SetCompare1(TIM3,cata+(u16)(CR1_val*ch1));
pa6=1;
}
if(pa6==1)
{
TIM_SetCompare1(TIM3,cata+(u16)(CR1_val*(1-ch1)));
pa6=0;
}
}
if(TIM_GetITStatus(TIM3,TIM_IT_CC2)!=RESET)
{
TIM_ClearITPendingBit(TIM3,TIM_IT_CC2);
cata=TIM_GetCapture2(TIM3);
if(pa7==0)
{
TIM_SetCompare2(TIM3,cata+(u16)(CR2_val*ch2));
pa7=1;
}
if(pa7==1)
{
TIM_SetCompare2(TIM3,cata+(u16)(CR2_val*(1-ch2)));
pa7=0;
}
}
}
3.adc
#include "adc.h"
void adc_init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
ADC_InitTypeDef ADC_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_ADC1,ENABLE);
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AIN;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStruct);
ADC_InitStruct.ADC_ContinuousConvMode=DISABLE;
ADC_InitStruct.ADC_DataAlign=ADC_DataAlign_Right;
ADC_InitStruct.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;
ADC_InitStruct.ADC_Mode=ADC_Mode_Independent;
ADC_InitStruct.ADC_NbrOfChannel=1;
ADC_InitStruct.ADC_ScanConvMode=DISABLE;
ADC_Init(ADC1,&ADC_InitStruct);
ADC_RegularChannelConfig(ADC1,ADC_Channel_8,1,ADC_SampleTime_1Cycles5);
ADC_Cmd(ADC1,ENABLE);
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
}
unsigned int adc_scanf(void)
{
ADC_SoftwareStartConvCmd(ADC1,ENABLE);
while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));
return ADC_GetConversionValue(ADC1);
}
4.led
#include "led.h"
void led_init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD,ENABLE);
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin=led1|led2|led3|led4|led5|led6|led7|led8;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOC,&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_2;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOD,&GPIO_InitStruct);
GPIO_SetBits(GPIOD,GPIO_Pin_2);
GPIO_SetBits(GPIOC,ledALL);
GPIO_ResetBits(GPIOD,GPIO_Pin_2);
}
void led_scanf(unsigned char mode ,unsigned int led)
{
if(mode==1)
{
GPIO_SetBits(GPIOD,GPIO_Pin_2);
GPIO_SetBits(GPIOC,led);
GPIO_ResetBits(GPIOD,GPIO_Pin_2);
}
else if(mode==0)
{
GPIO_SetBits(GPIOD,GPIO_Pin_2);
GPIO_ResetBits(GPIOC,led);
GPIO_ResetBits(GPIOD,GPIO_Pin_2);
}
}
5.key
#include "key.h"
#include "lcd.h"
void key_init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_8;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_2|GPIO_Pin_1;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStruct);
}
unsigned char key_scanf(void)
{
unsigned char key_but=0;
if(key1==0||key2==0||key3==0||key4==0)
{
Delay_LCD(200);
if(key1==0) key_but=1;
if(key2==0) key_but=2;
if(key3==0) key_but=3;
if(key4==0) key_but=4;
}
return key_but;
}
注意:对于自动模式我们发现电压值与占空比是成除3.3的关系的,因此我们在自动模式中用adc的值除3.3,当adc=3.3时占空比为100%,当adc=0时占空比=0;
总结
这是我第一次写的文章可能不是写的很好,大家多担待一下。
另外说明一下在lcd.c上LCD_WriteReg(),LCD_WriteRAM_Prepare(),LCD_WriteRAM()三个函数中首行加上u16 pcout=GPIOC->ODR,最后一行加上GPIOC->ODR=pcout。用于锁存HC573.