频率控制器的功能设计与实现
在根据蓝桥杯题目设计工程代码时注意的为:先一步一步实现功能,每做一个功能最好设计一个副本,这样才能保证制作好的功能不丢失,哪怕新设计的功能无效也能迅速回退到上个功能版本。
在本届国赛题的难点为:脉冲捕获、分频和倍频输出、双路ADC;其它的如LED,LCD,E2PROM都是相对简单的,在此不做赘述。
1、脉冲捕获,根据扩展板和原理图可以知道连接的为PA1和PA2接口。运用的为定时器2,CH2和CH3通道进行脉冲捕获。.h和.c代码如下:
#ifndef __BSP_GENERALCAP_H
#define __BSP_GENERALCAP_H
#include "stm32f10x.h"
#include "Def_config.h"
/************通用定时器TIM参数定义,只限TIM2、3、4************/
// 定时器输入捕获用户自定义变量结构体声明
typedef struct
{
u8 Capture_StartFlag; // 捕获开始标志位
u32 Capture_CcrValue_1;
u32 Capture_CcrValue_2;
u32 Capture_CcrValue; // 捕获寄存器的值
u32 Capture_Period; // 溢出次数 。计算后手动清零!
u32 Capture_Frequency; //频率
JUDGE_ENUM Capture_Success; //成功标志
}TIM_ICUserValueTypeDef;
extern TIM_ICUserValueTypeDef TIM_ICUserValueStructure;
extern TIM_ICUserValueTypeDef TIM_ICUserValueStructure_CH3;
#define GENERAL_CAP_IRQ TIM2_IRQn
#define GENERAL_CAP_TIM TIM2
#define GENERAL_CAP_CLK RCC_APB1Periph_TIM2
#define GENERAL_CAP_CHANNEL_02 TIM_Channel_2
#define GENERAL_CAP_GPIO_CLK RCC_APB2Periph_GPIOA
#define GENERAL_CAP_PORT GPIOA
#define GENERAL_CAP_PIN_02 GPIO_Pin_1
#define GENERAL_CAP_ITCCR_02 TIM_IT_CC2
#define GENERAL_CAP_GetCapture_02 TIM_GetCapture2
// CH3
#define GENERAL_CAP_CHANNE0L_03 TIM_Channel_3
#define GENERAL_CAP_PIN_03 GPIO_Pin_2
#define GENERAL_CAP_ITCCR_03 TIM_IT_CC3
#define GENERAL_CAP_GetCapture_03 TIM_GetCapture3
/**************************函数声明********************************/
extern void GENERAL_CAP_Init(void);
extern void GENERAL_CAP_Interrupt(void);
/********************* TIM3 CAP******************************
#define GENERAL_CAP_IRQ TIM3_IRQn
#define GENERAL_CAP_TIM TIM3
#define GENERAL_CAP_CLK RCC_APB1Periph_TIM3
#define GENERAL_CAP_CHANNEL TIM_Channel_2
#define GENERAL_CAP_GPIO_CLK RCC_APB2Periph_GPIOA
#define GENERAL_CAP_PORT GPIOA
#define GENERAL_CAP_PIN GPIO_Pin_7
#define GENERAL_CAP_ITCCR_02 TIM_IT_CC2
#define GENERAL_CAP_GetCapture_02 TIM_GetCapture2
************************************************************/
#endif
#include "bsp_GeneralCap.h"
static void GENERAL_TIM_NVIC_CapConfig(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel = GENERAL_CAP_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_Priority_Structure.CAP_Priority;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
static void GENERAL_TIM_GPIO_CapConfig(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(GENERAL_CAP_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = GENERAL_CAP_PIN_02 | GENERAL_CAP_PIN_03;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GENERAL_CAP_PORT, &GPIO_InitStructure);
}
static void GENERAL_TIM_Mode_CapConfig(void)
{
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(GENERAL_CAP_CLK,ENABLE);
TIM_TimeBaseStructure.TIM_Period = 0xffff;
TIM_TimeBaseStructure.TIM_Prescaler = 71;
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInit(GENERAL_CAP_TIM, &TIM_TimeBaseStructure);
TIM_ICInitStructure.TIM_Channel = GENERAL_CAP_CHANNEL_02;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICFilter = 0;
TIM_ICInit(GENERAL_CAP_TIM, &TIM_ICInitStructure);
TIM_ICInitStructure.TIM_Channel = GENERAL_CAP_CHANNE0L_03;
TIM_ICInit(GENERAL_CAP_TIM, &TIM_ICInitStructure);
TIM_ITConfig (GENERAL_CAP_TIM, TIM_IT_Update | GENERAL_CAP_ITCCR_02 | GENERAL_CAP_ITCCR_03, ENABLE );
TIM_Cmd(GENERAL_CAP_TIM, ENABLE);
}
void GENERAL_CAP_Init(void)
{
GENERAL_TIM_GPIO_CapConfig();
GENERAL_TIM_NVIC_CapConfig();
GENERAL_TIM_Mode_CapConfig();
}
TIM_ICUserValueTypeDef TIM_ICUserValueStructure = {0,0,0,0,0,0,FALSE};
TIM_ICUserValueTypeDef TIM_ICUserValueStructure_CH3 = {0,0,0,0,0,0,FALSE};
void GENERAL_CAP_Interrupt(void)
{
if(TIM_GetFlagStatus(GENERAL_CAP_TIM,TIM_IT_Update) == SET){
TIM_ClearITPendingBit(GENERAL_CAP_TIM,TIM_IT_Update);
if(TIM_ICUserValueStructure.Capture_Success == FALSE)
{
TIM_ICUserValueStructure.Capture_Period ++;
if(TIM_ICUserValueStructure.Capture_Period > 16)
{
TIM_ICUserValueStructure.Capture_CcrValue_1 = 0;
TIM_ICUserValueStructure.Capture_CcrValue_2 = 0;
TIM_ICUserValueStructure.Capture_CcrValue = 0;
TIM_ICUserValueStructure.Capture_StartFlag = 0;
TIM_ICUserValueStructure.Capture_Frequency = 0;
TIM_ICUserValueStructure.Capture_Period = 0;
TIM_ICUserValueStructure.Capture_Success = TRUE;
}
}
if(TIM_ICUserValueStructure_CH3.Capture_Success == FALSE)
{
TIM_ICUserValueStructure_CH3.Capture_Period ++;
if(TIM_ICUserValueStructure_CH3.Capture_Period > 16)
{
TIM_ICUserValueStructure_CH3.Capture_CcrValue_1 = 0;
TIM_ICUserValueStructure_CH3.Capture_CcrValue_2 = 0;
TIM_ICUserValueStructure_CH3.Capture_CcrValue = 0;
TIM_ICUserValueStructure_CH3.Capture_StartFlag = 0;
TIM_ICUserValueStructure_CH3.Capture_Frequency = 0;
TIM_ICUserValueStructure_CH3.Capture_Period = 0;
TIM_ICUserValueStructure_CH3.Capture_Success = TRUE;
}
}
}
if(TIM_GetFlagStatus(GENERAL_CAP_TIM,GENERAL_CAP_ITCCR_02) == SET)
{
TIM_ClearITPendingBit(GENERAL_CAP_TIM,GENERAL_CAP_ITCCR_02);
if(TIM_ICUserValueStructure.Capture_Success == FALSE)
{
if(TIM_ICUserValueStructure.Capture_StartFlag == 0)
{
TIM_ICUserValueStructure.Capture_CcrValue_1 = GENERAL_CAP_GetCapture_02(GENERAL_CAP_TIM);
TIM_ICUserValueStructure.Capture_StartFlag = 1;
}
else
{
TIM_ICUserValueStructure.Capture_CcrValue_2 = GENERAL_CAP_GetCapture_02(GENERAL_CAP_TIM);
TIM_ICUserValueStructure.Capture_StartFlag = 0;
TIM_ICUserValueStructure.Capture_Success = TRUE;
}
}
}
if(TIM_GetFlagStatus(GENERAL_CAP_TIM,GENERAL_CAP_ITCCR_03) == SET)
{
TIM_ClearITPendingBit(GENERAL_CAP_TIM,GENERAL_CAP_ITCCR_03);
if(TIM_ICUserValueStructure_CH3.Capture_Success == FALSE)
{
if(TIM_ICUserValueStructure_CH3.Capture_StartFlag == 0)
{
TIM_ICUserValueStructure_CH3.Capture_CcrValue_1 = GENERAL_CAP_GetCapture_03(GENERAL_CAP_TIM);
TIM_ICUserValueStructure_CH3.Capture_StartFlag = 1;
}
else
{
TIM_ICUserValueStructure_CH3.Capture_CcrValue_2 = GENERAL_CAP_GetCapture_03(GENERAL_CAP_TIM);
TIM_ICUserValueStructure_CH3.Capture_StartFlag = 0;
TIM_ICUserValueStructure_CH3.Capture_Success = TRUE;
}
}
}
}
调用方法思路:捕获函数其实仅仅是通过定时器将脉冲进行计数,但是具体的计算放到了main函数里,这样不占用太多中断时间,采集效果会好点。(中断里最好节省时间,能不用乘除法就不用,因为需要耗费时钟周期较久。)
if(TIM_ICUserValueStructure.Capture_Success == TRUE)
{
TIM_Cmd(GENERAL_CAP_TIM, DISABLE);
if(TIM_ICUserValueStructure.Capture_Period == 0)
{
TIM_ICUserValueStructure.Capture_CcrValue = (TIM_ICUserValueStructure.Capture_CcrValue_2 - TIM_ICUserValueStructure.Capture_CcrValue_1);
}
else
{
TIM_ICUserValueStructure.Capture_CcrValue = (65536 * TIM_ICUserValueStructure.Capture_Period - TIM_ICUserValueStructure.Capture_CcrValue_1 + TIM_ICUserValueStructure.Capture_CcrValue_2);
}
if(TIM_ICUserValueStructure.Capture_CcrValue != 0)
TIM_ICUserValueStructure.Capture_Frequency = (u32)(1000000.0 / (TIM_ICUserValueStructure.Capture_CcrValue) + 0.5);
else
TIM_ICUserValueStructure.Capture_Frequency = 0;
LCDDISVALUE_DEF_Structure.Pulse_01 = TIM_ICUserValueStructure.Capture_Frequency;
if(TIM_ICUserValueStructure.Capture_Frequency != Capture01_Frequency_Last)
{
Capture01_Frequency_Last = TIM_ICUserValueStructure.Capture_Frequency;
PWMTIM_Structure.PWMx_Ch1_Freq = GENERAL_PWM_Period_FrequencySet((u16)(TIM_ICUserValueStructure.Capture_Frequency*1.0/LCDDISVALUE_SET_Structure.Division_PA6_PA1));
PWMTIM_Structure.PWMx_Ch1_DutyCycle = 0.5;
PWMTIM_Structure.PWMx_Ch1_Freq_LowVolt = (u16)(PWMTIM_Structure.PWMx_Ch1_Freq * (1 - PWMTIM_Structure.PWMx_Ch1_DutyCycle));
PWMTIM_Structure.PWMx_Ch1_Freq_highVolt = (u16)(PWMTIM_Structure.PWMx_Ch1_Freq * PWMTIM_Structure.PWMx_Ch1_DutyCycle);
}
TIM_ICUserValueStructure.Capture_CcrValue_1 = 0;
TIM_ICUserValueStructure.Capture_CcrValue_2 = 0;
TIM_ICUserValueStructure.Capture_CcrValue = 0;
TIM_ICUserValueStructure.Capture_StartFlag = 0;
TIM_ICUserValueStructure.Capture_Frequency = 0; //频率为0
TIM_ICUserValueStructure.Capture_Period = 0;
TIM_ICUserValueStructure.Capture_Success = FALSE;
TIM_Cmd(GENERAL_CAP_TIM, ENABLE);
}
if(TIM_ICUserValueStructure_CH3.Capture_Success == TRUE)
{
TIM_Cmd(GENERAL_CAP_TIM, DISABLE);
if(TIM_ICUserValueStructure_CH3.Capture_Period == 0)
{
TIM_ICUserValueStructure_CH3.Capture_CcrValue = (TIM_ICUserValueStructure_CH3.Capture_CcrValue_2 - TIM_ICUserValueStructure_CH3.Capture_CcrValue_1);
}
else
{
TIM_ICUserValueStructure_CH3.Capture_CcrValue = (65536 * TIM_ICUserValueStructure_CH3.Capture_Period - TIM_ICUserValueStructure_CH3.Capture_CcrValue_1 + TIM_ICUserValueStructure_CH3.Capture_CcrValue_2);
}
if(TIM_ICUserValueStructure_CH3.Capture_CcrValue != 0)
TIM_ICUserValueStructure_CH3.Capture_Frequency = (u32)(1000000.0 / (TIM_ICUserValueStructure_CH3.Capture_CcrValue) + 0.5); // (1000000.0 / (TIM_ICUserValueStructure_CH3.Capture_CcrValue) + 0.5) 得结果为HZ,需要转为KHz
else
TIM_ICUserValueStructure_CH3.Capture_Frequency = 0;
LCDDISVALUE_DEF_Structure.Pulse_02 = TIM_ICUserValueStructure_CH3.Capture_Frequency;
if(TIM_ICUserValueStructure_CH3.Capture_Frequency != Capture02_Frequency_Last)
{
Capture02_Frequency_Last = TIM_ICUserValueStructure_CH3.Capture_Frequency;
PWMTIM_Structure.PWMx_Ch2_Freq = GENERAL_PWM_Period_FrequencySet((u16)(TIM_ICUserValueStructure_CH3.Capture_Frequency * LCDDISVALUE_SET_Structure.Multiply_PA7_PA2));
PWMTIM_Structure.PWMx_Ch2_DutyCycle = 0.5;
PWMTIM_Structure.PWMx_Ch2_Freq_LowVolt = (u16)(PWMTIM_Structure.PWMx_Ch2_Freq * (1 - PWMTIM_Structure.PWMx_Ch2_DutyCycle));
PWMTIM_Structure.PWMx_Ch2_Freq_highVolt = (u16)(PWMTIM_Structure.PWMx_Ch2_Freq * PWMTIM_Structure.PWMx_Ch2_DutyCycle);
}
TIM_ICUserValueStructure_CH3.Capture_CcrValue_1 = 0;
TIM_ICUserValueStructure_CH3.Capture_CcrValue_2 = 0;
TIM_ICUserValueStructure_CH3.Capture_CcrValue = 0;
TIM_ICUserValueStructure_CH3.Capture_StartFlag = 0;
TIM_ICUserValueStructure_CH3.Capture_Frequency = 0; //频率为0
TIM_ICUserValueStructure_CH3.Capture_Period = 0;
TIM_ICUserValueStructure_CH3.Capture_Success = FALSE;
TIM_Cmd(GENERAL_CAP_TIM, ENABLE);
}
分频和倍频输出,.c和.h都放出。调用方法在捕获的调用方法里已经给出,就是判断当频率和上次存的频率不同时,通过通过PWM的Toggle模式输出的值。
#ifndef __BSP_GENERALPWM_H
#define __BSP_GENERALPWM_H
#include "stm32f10x.h"
#include "Def_config.h"
typedef struct{
__IO u16 PWMx_Ch1_Freq;
float PWMx_Ch1_DutyCycle;
__IO u16 PWMx_Ch1_Freq_LowVolt;
__IO u16 PWMx_Ch1_Freq_highVolt;
__IO u16 PWMx_Ch2_Freq;
float PWMx_Ch2_DutyCycle;
__IO u16 PWMx_Ch2_Freq_LowVolt;
__IO u16 PWMx_Ch2_Freq_highVolt;
JUDGE_ENUM TIM3_OutputLowVolt;
}PWMTIM_TypeDef;
extern PWMTIM_TypeDef PWMTIM_Structure;
/******************* PWM模式调节TIM3 *************************/
#define GENERAL_PWM_TIM TIM3
/******************* PWM模式调节 TIM_OCMode_Toggle*************************/
#define TIM_OCMode_SET TIM_OCMode_Toggle
//最低输出20HZ,最高1M TIM_OCMode_Toggle下TIM_OCInitStructure.TIM_Pulse的值,决定频率
#define GENERAL_PWM_Period_FrequencySet(X) (u16)(1000000.0/X + 0.5) //X:Frequency
#define GENERAL_PWM_CCRx PWMTIM_Structure.PWMx_Ch1_Freq
#define GENERAL_PWM_CCRx_CH2 PWMTIM_Structure.PWMx_Ch2_Freq
/**************************函数声明********************************/
extern void GENERAL_PWM_Init(void);
void GENERAL_PWM_FrequecyAndDutyCycle(STATE_ENUM TIM3_OutputState);
extern void GENERAL_PWM_Interrupt(void);
#endif /* __BSP_GENERALPWME_H */
#include "bsp_GeneralPwm.h"
static void GENERAL_PWM_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, 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);
}
static void GENERAL_NORMAL_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
static void GENERAL_PWM_NVIC_PwmConfig(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_Priority_Structure.PWM_Priority;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
static void GENERAL_PWM_Mode_Config(void)
{
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
TIM_TimeBaseStructure.TIM_Period = 0xffff;
TIM_TimeBaseStructure.TIM_Prescaler= 71;
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInit(GENERAL_PWM_TIM, &TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_SET;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_Pulse = GENERAL_PWM_CCRx;
TIM_OC1Init(GENERAL_PWM_TIM, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(GENERAL_PWM_TIM, TIM_OCPreload_Disable);
TIM_OCInitStructure.TIM_Pulse = GENERAL_PWM_CCRx_CH2;
TIM_OC2Init(GENERAL_PWM_TIM, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(GENERAL_PWM_TIM, TIM_OCPreload_Disable);
TIM_ITConfig(GENERAL_PWM_TIM,TIM_IT_CC1 | TIM_IT_CC2,ENABLE);
TIM_Cmd(GENERAL_PWM_TIM, ENABLE);
}
PWMTIM_TypeDef PWMTIM_Structure;
void GENERAL_PWM_Init(void)
{
PWMTIM_Structure.PWMx_Ch1_Freq = GENERAL_PWM_Period_FrequencySet(1000);
PWMTIM_Structure.PWMx_Ch1_DutyCycle = 0.5;
PWMTIM_Structure.PWMx_Ch1_Freq_LowVolt = (u16)(PWMTIM_Structure.PWMx_Ch1_Freq * (1 - PWMTIM_Structure.PWMx_Ch1_DutyCycle));
PWMTIM_Structure.PWMx_Ch1_Freq_highVolt = (u16)(PWMTIM_Structure.PWMx_Ch1_Freq * PWMTIM_Structure.PWMx_Ch1_DutyCycle);
PWMTIM_Structure.PWMx_Ch2_Freq = GENERAL_PWM_Period_FrequencySet(2000);
PWMTIM_Structure.PWMx_Ch2_DutyCycle = 0.5;
PWMTIM_Structure.PWMx_Ch2_Freq_LowVolt = (u16)(PWMTIM_Structure.PWMx_Ch2_Freq * (1 - PWMTIM_Structure.PWMx_Ch2_DutyCycle));
PWMTIM_Structure.PWMx_Ch2_Freq_highVolt = (u16)(PWMTIM_Structure.PWMx_Ch2_Freq * PWMTIM_Structure.PWMx_Ch2_DutyCycle);
GENERAL_PWM_GPIO_Config();
GENERAL_PWM_NVIC_PwmConfig();
GENERAL_PWM_Mode_Config();
}
void GENERAL_PWM_FrequecyAndDutyCycle(STATE_ENUM TIM3_OutputState)
{
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_ITConfig(GENERAL_PWM_TIM,TIM_IT_CC1 | TIM_IT_CC2,DISABLE);
TIM_Cmd(GENERAL_PWM_TIM, DISABLE);
if(TIM3_OutputState == ON)
{
GENERAL_PWM_GPIO_Config();
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_SET;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_Pulse = PWMTIM_Structure.PWMx_Ch1_Freq;
TIM_OC1Init(GENERAL_PWM_TIM, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(GENERAL_PWM_TIM, TIM_OCPreload_Disable);
TIM_OCInitStructure.TIM_Pulse = PWMTIM_Structure.PWMx_Ch2_Freq;
TIM_OC2Init(GENERAL_PWM_TIM, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(GENERAL_PWM_TIM, TIM_OCPreload_Disable);
TIM_ITConfig(GENERAL_PWM_TIM,TIM_IT_CC1 | TIM_IT_CC2,ENABLE);
TIM_Cmd(GENERAL_PWM_TIM, ENABLE);
}
else
{
GENERAL_NORMAL_GPIO_Config();
if(PWMTIM_Structure.TIM3_OutputLowVolt == TRUE)
GPIO_ResetBits(GPIOA,GPIO_Pin_6 | GPIO_Pin_7);
else
GPIO_SetBits(GPIOA,GPIO_Pin_6 | GPIO_Pin_7);
}
}
u8 PWM_Interrupt_Count = 0;
u8 PWM_Interrupt_Count_CH2 = 0;
void GENERAL_PWM_Interrupt(void)
{
u16 capture = 0;
if(TIM_GetFlagStatus(GENERAL_PWM_TIM,TIM_IT_CC1) == SET)
{
TIM_ClearITPendingBit(GENERAL_PWM_TIM,TIM_IT_CC1);
capture = TIM_GetCapture1(GENERAL_PWM_TIM);
if(PWM_Interrupt_Count == 0)
{
TIM_SetCompare1(GENERAL_PWM_TIM,capture + PWMTIM_Structure.PWMx_Ch1_Freq_LowVolt);
PWM_Interrupt_Count = 1;
}
else
{
TIM_SetCompare1(GENERAL_PWM_TIM,capture + PWMTIM_Structure.PWMx_Ch1_Freq_highVolt);
PWM_Interrupt_Count = 0;
}
}
if(TIM_GetFlagStatus(GENERAL_PWM_TIM,TIM_IT_CC2) == SET)
{
TIM_ClearITPendingBit(GENERAL_PWM_TIM,TIM_IT_CC2);
capture = TIM_GetCapture2(GENERAL_PWM_TIM);
if(PWM_Interrupt_Count_CH2 == 0)
{
TIM_SetCompare2(GENERAL_PWM_TIM,capture + PWMTIM_Structure.PWMx_Ch2_Freq_LowVolt);
PWM_Interrupt_Count_CH2 = 1;
}
else
{
TIM_SetCompare2(GENERAL_PWM_TIM,capture + PWMTIM_Structure.PWMx_Ch2_Freq_highVolt);
PWM_Interrupt_Count_CH2 = 0;
}
}
}
双通道ADC扫描(中断模式)
采用此模式也可以,当然也可以采用DMA模式。更加方便和直接。由于本人也是从入门开始学习STM32来参加比赛的,在准备的这些时间,一步一步不断更新自己的思维逻辑和功能实现方法,后续会有DMA方式的代码。
#ifndef __ADC_H
#define __ADC_H
#include "stm32f10x.h"
#include "Def_config.h"
// ADC 编号选择
// 可以是 ADC1/2,如果使用ADC3,中断相关的要改成ADC3的
#define ADCx ADC1
#define ADC_CLK RCC_APB2Periph_ADC1
// ADC GPIO宏定义
// 注意:用作ADC采集的IO必须没有复用,否则采集电压会有影响
#define ADC_GPIO_CLK RCC_APB2Periph_GPIOA
#define ADC_PORT GPIOA
#define ADC_PIN (GPIO_Pin_4 | GPIO_Pin_5)
// ADC 通道宏定义
//#define ADC_CHANNEL ADC_Channel_8
// ADC 中断相关宏定义
#define ADC_IRQ ADC1_2_IRQn
#define ADC_IRQHandler ADC1_2_IRQHandler
//#define ADC_IRQ ADC3_IRQn
//#define ADC_IRQHandler ADC3_IRQHandler
typedef struct{
uint16_t ADC_ConvertedValue;
float ADC_Voltage;
JUDGE_ENUM IS_ADCConvertComplete;
}ADCREAD_TypeDef;
extern ADCREAD_TypeDef ADCREAD_Structure;
extern void ADCx_Init(void);
extern void ADC_Read_Interrupt(void);
#endif /* __ADC_H */
#include "bsp_adc.h"
static void ADC_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel = ADC_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_Priority_Structure.ADC1_RPx_Priority;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
static void ADCx_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( ADC_GPIO_CLK, ENABLE );
GPIO_InitStructure.GPIO_Pin = ADC_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(ADC_PORT, &GPIO_InitStructure);
}
static void ADCx_Mode_Config(void)
{
ADC_InitTypeDef ADC_InitStructure;
RCC_APB2PeriphClockCmd( ADC_CLK, ENABLE );
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(ADCx, &ADC_InitStructure);
RCC_ADCCLKConfig(RCC_PCLK2_Div8);
ADC_RegularChannelConfig(ADCx, ADC_Channel_4, 1, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADCx, ADC_Channel_5, 1, ADC_SampleTime_55Cycles5);
ADC_ITConfig(ADCx, ADC_IT_EOC, ENABLE);
ADC_Cmd(ADCx, ENABLE);
ADC_ResetCalibration(ADCx);
while(ADC_GetResetCalibrationStatus(ADCx));
ADC_StartCalibration(ADCx);
while(ADC_GetCalibrationStatus(ADCx));
ADC_SoftwareStartConvCmd(ADCx, ENABLE);
ADC_RegularChannelConfig(ADCx, ADC_Channel_4, 1, ADC_SampleTime_55Cycles5);
}
void ADCx_Init(void)
{
ADCx_GPIO_Config();
ADCx_Mode_Config();
ADC_NVIC_Config();
}
ADCREAD_TypeDef ADCREAD_Structure;
void ADC_Read_Interrupt(void)
{
if (ADC_GetITStatus(ADCx,ADC_IT_EOC) == SET)
{
ADC_ClearITPendingBit(ADCx,ADC_IT_EOC);
ADCREAD_Structure.ADC_ConvertedValue = ADC_GetConversionValue(ADCx);
ADCREAD_Structure.IS_ADCConvertComplete = TRUE;
}
}
END:当开始写国赛系列的博客时,已经结束了本年度的蓝桥杯国赛比赛,这些程序都是训练过程中写的代码,难免有所不足,望见谅。