分析
此次赛题围绕两个方向,结构如下:
代码:
1.主函数模块
main.c
#include <stm32f10x.h>
#include "lcd.h"
#include "adc.h"
#include "lcd_window.h"
#include "pwm.h"
#include "key.h"
#include "led.h"
float ADC_Value;
float CH1_duty=0.1,CH2_duty=0.1;
u8 channel_1_flag,channel_2_flag;
u8 setting_mode=0; //0 AUTO 1 MANU
u8 Data_Para=0; //0 Data 1 Para
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
SysTick_Config(SystemCoreClock/1000);
STM3210B_LCD_Init();
LCD_Clear(Black);
LCD_SetBackColor(Black);
LCD_SetTextColor(White);
adc_Init();
pwm_Init();
KEY_Init();
LED_Init();
while(1)
{
lcd_window();
KEY_Control();
LED_Control();
}
}
在这里插入代码片
2.ADC模块
adc.c
#include <stm32f10x.h>
#include "adc.h"
void adc_Init(void)
{
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
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_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_13Cycles5);
ADC_Cmd(ADC1, ENABLE);
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
//ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}
float ADC_GetValue(void)
{
float ADC_V;
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==RESET);
ADC_V=ADC_GetConversionValue(ADC1)*3.30/0xfff;
return ADC_V;
}
在这里插入代码片
ADC.h
#ifndef __ADC_H
#define __ADC_H
void adc_Init(void);
float ADC_GetValue(void);
#endif
在这里插入代码片
3.按键模块
key.c
#include "stm32f10x.h"
#include "stm32f10x_it.h"
#include "key.h"
#include "lcd.h"
extern u8 setting_mode; //0锟斤拷示AUTO 1锟斤拷示MANU
extern u8 Data_Para; //0锟斤拷示Data页锟斤拷 1锟斤拷示Para页锟斤拷
extern float CH1_duty,CH2_duty;
float ch1_duty_1=0.1,ch2_duty_1=0.1;
u8 key1_sum,key2_sum,key3_sum,key4_sum;
void KEY_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
void KEY_Control(void)
{
if(KEY1==0)
{
delay_ms(10);
if(KEY1==0)
{ key1_sum++;
LCD_ClearLine(Line0);
LCD_ClearLine(Line1);
LCD_ClearLine(Line2);
LCD_ClearLine(Line3);
LCD_ClearLine(Line4);
LCD_ClearLine(Line5);
LCD_ClearLine(Line6);
LCD_ClearLine(Line7);
LCD_ClearLine(Line8);
LCD_ClearLine(Line9);
}
if(key1_sum==1)
{
if(setting_mode==1)
{
Data_Para^=1;
}
else
{
Data_Para=0;
}
}
}
else
{
key1_sum=0;
}
if(KEY2==0)
{
delay_ms(10);
if(KEY2==0)
{
key2_sum++;
if(key2_sum==1)
{
if(setting_mode==1)
{
ch1_duty_1+=0.1;
if((ch1_duty_1-1.0)>=0)
{
ch1_duty_1=0.1;
}
}
}
}
}
else
{
key2_sum=0;
}
if(KEY3==0)
{
delay_ms(10);
if(KEY3==0)
{ key3_sum++;
if(key3_sum==1)
{
if(setting_mode==1)
{
ch2_duty_1+=0.1;
if((ch2_duty_1-1.0)>=0)
{
ch2_duty_1=0.1;
}
}
}
}
}
else
{
key3_sum=0;
}
if(KEY4==0)
{
delay_ms(10);
if(KEY4==0)
{
key4_sum++;
if(key4_sum==1)
{
setting_mode^=1;
}
}
}
else
{
key4_sum=0;
}
}
这里的按键模块我觉得是一个很好的按键消抖方法(是参照那些前辈们这样写的)。
key.h
#ifndef __KEY_H
#define __KEY_H
#include "stm32f10x.h"
#define KEY1 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)
#define KEY2 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_8)
#define KEY3 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)
#define KEY4 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_2)
void KEY_Init(void);
void KEY_Control(void);
#endif
在这里插入代码片
4.LED模块
#include "stm32f10x.h"
#include "led.h"
extern u8 setting_mode;
extern u8 Data_Para;
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Pin = LED1|LED2|LED3|LED4|LED5|LED6|LED7|LED8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_2;
GPIO_Init(GPIOD, &GPIO_InitStructure);
}
void LED_Status(uint16_t LED,u8 state)
{
// GPIO_Write(GPIOC,0xff00); //全灭
// GPIO_SetBits(GPIOD,GPIO_Pin_2);//
// GPIO_ResetBits(GPIOD,GPIO_Pin_2);
if(state) //on
{
GPIO_ResetBits(GPIOC,LED);
GPIO_SetBits(GPIOD,GPIO_Pin_2);//
GPIO_ResetBits(GPIOD,GPIO_Pin_2);
}
else
{
GPIO_SetBits(GPIOC,LED);
GPIO_SetBits(GPIOD,GPIO_Pin_2);//
GPIO_ResetBits(GPIOD,GPIO_Pin_2);
}
}
void LED_Control(void)
{
GPIO_Write(GPIOC,0xff00); //全灭
GPIO_SetBits(GPIOD,GPIO_Pin_2);// 此处需要特别注意,应该在这里添加这三行代码
GPIO_ResetBits(GPIOD,GPIO_Pin_2);
if(setting_mode==1)
{
LED_Status(LED1,0);
}
if(setting_mode==0)
{
LED_Status(LED1,1);
}
if(Data_Para==0)
{
LED_Status(LED2,1);
}
else
{
LED_Status(LED2,0);
}
}
LED.H
#ifndef __LED_H
#define __LED_H
#include "stm32f10x.h"
#define LED1 GPIO_Pin_8
#define LED2 GPIO_Pin_9
#define LED3 GPIO_Pin_10
#define LED4 GPIO_Pin_11
#define LED5 GPIO_Pin_12
#define LED6 GPIO_Pin_13
#define LED7 GPIO_Pin_14
#define LED8 GPIO_Pin_15
void LED_Init(void);
void LED_Status(uint16_t LED,u8 state);
void LED_Control(void);
#endif
5.pwm模块
pwm.c
#include <stm32f10x.h>
#include "pwm.h"
extern float CH1_duty,CH2_duty;
extern u8 channel_1_flag,channel_2_flag;
__IO uint16_t CCR1_Val =10000; //72000000/72/100 ---100HZ
__IO uint16_t CCR2_Val =5000; //72000000/72/200 ---200HZ
void pwm_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE); //注意要是能复用时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_TimeBaseStructure.TIM_Period = 65535;
TIM_TimeBaseStructure.TIM_Prescaler = 72-1;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle; //记住
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = CCR1_Val;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Disable);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = CCR2_Val;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OC2Init(TIM3, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Disable);
TIM_Cmd(TIM3, ENABLE);
TIM_ITConfig(TIM3, TIM_IT_CC2|TIM_IT_CC1, ENABLE);
TIM_SetCounter(TIM3,0x0);
TIM_SetCompare2(TIM3,0x0);
TIM_SetCompare3(TIM3,0x0);
}
void TIM3_IRQHandler(void)
{
u16 capture; //注意这里时u16,之前用得是u8不行。
if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_CC1);
capture = TIM_GetCapture1(TIM3);
if(channel_1_flag)
{
TIM_SetCompare1(TIM3, capture + (u16)CCR1_Val*CH1_duty);
}
else
{
TIM_SetCompare1(TIM3, capture + (u16)CCR1_Val*(1-CH1_duty));
}
channel_1_flag^=1;
}
if (TIM_GetITStatus(TIM3, TIM_IT_CC2) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
capture = TIM_GetCapture2(TIM3);
if(channel_2_flag)
{
TIM_SetCompare2(TIM3, (u16)(capture + CCR2_Val*CH2_duty));
}
else
{
TIM_SetCompare2(TIM3, (u16)(capture + CCR2_Val*(1-CH2_duty)));
}
channel_2_flag^=1;
}
}
在这里插入代码片
该方法既可以调节占空比,也可以调节频率,题目要求只需调节占空比即可。同时有个地方注意一下: CH1_duty,CH2_duty这里我定义的是用float型来表示占空比,这样CH1_duty,CH2_duty直接就是小数,而当我把CH1_duty,CH2_duty,定义为u16时,用CH1_duty/100,CH2_duty/100来表示占空比时,PWM就无法正常输出。
pwm.h
#ifndef __PWM_H
#define __PWM_H
void pwm_Init(void);
#endif
结果