第八届决赛题目考察的知识主要是adc和频率发生和捕获。不知是不是第一次用到扩展板的缘故,考察的知识点不算多。
工程结构
init.c (需要注意的是,因为用到两路adc,这里我们采用注入通道的方法,可以参考前文)
#include "stm32f10x.h"
#include "lcd.h"
#include "init.h"
#include "i2c.h"
#include "stdio.h"
void GPIO_Int(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |
RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD, ENABLE);
//led
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10| GPIO_Pin_11| GPIO_Pin_12| GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_Init(GPIOD, &GPIO_InitStructure);
//key
//led
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOC,GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10| GPIO_Pin_11| GPIO_Pin_12| GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15);
GPIO_SetBits(GPIOD,GPIO_Pin_2);
GPIO_ResetBits(GPIOD,GPIO_Pin_2);
//adc
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &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);
/* ADC1 regular channel4 、5 configuration */
ADC_InjectedChannelConfig(ADC1, ADC_Channel_4, 1, ADC_SampleTime_1Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 1, ADC_SampleTime_1Cycles5);
ADC_AutoInjectedConvCmd(ADC1,ENABLE);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
/* Start ADC1 calibration */
ADC_StartCalibration(ADC1);
/* Check the end of ADC1 calibration */
while(ADC_GetCalibrationStatus(ADC1));
}
void LCD_Init(void)
{
STM3210B_LCD_Init();
LCD_Clear(Blue);
LCD_SetBackColor(Blue);
LCD_SetTextColor(White);
SysTick_Config(SystemCoreClock/1000);
LCD_DisplayStringLine(Line0," Measure ");
LCD_DisplayStringLine(Line1," ");
LCD_DisplayStringLine(Line2," PLUS1 : 2kHz ");
LCD_DisplayStringLine(Line3," ");
LCD_DisplayStringLine(Line4," PLUS2 : 1kHz ");
LCD_DisplayStringLine(Line5," ");
LCD_DisplayStringLine(Line6," AO1 : 2.20V ");
LCD_DisplayStringLine(Line7," ");
LCD_DisplayStringLine(Line8," AO2 : 3.00V ");
LCD_DisplayStringLine(Line9," 1");
}
unsigned char I2C_Read(unsigned char add)
{
unsigned char temp;
I2CStart();
I2CSendByte(0xa0);
I2CSendAck();
I2CSendByte(add);
I2CSendAck();
I2CStart();
I2CSendByte(0xa1);
I2CSendAck();
temp=I2CReceiveByte();
I2CSendAck();
I2CStop();
return temp;
}
void I2C_Write(unsigned char add,unsigned char dat)
{
I2CStart();
I2CSendByte(0xa0);
I2CSendAck();
I2CSendByte(add);
I2CSendAck();
I2CSendByte(dat);
I2CSendAck();
I2CStop();
}
void TIM2_ICInit(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
GPIO_InitTypeDef GPIO_InitStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
//NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_TimeBaseStructure.TIM_Period = 65535;
TIM_TimeBaseStructure.TIM_Prescaler = 71;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2|TIM_Channel_3;
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 = 0x0;
TIM_ICInit(TIM2, &TIM_ICInitStructure);
TIM_Cmd(TIM2, ENABLE);
TIM_ITConfig(TIM2, TIM_IT_CC2|TIM_IT_CC3, ENABLE);
/* Enable the TIM3 global Interrupt
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure); */
}
void TIM3_OCInit(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
GPIO_InitTypeDef GPIO_InitStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
//NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
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);
TIM_TimeBaseStructure.TIM_Period = 65535;
TIM_TimeBaseStructure.TIM_Prescaler = 71;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 250;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
TIM_OC2Init(TIM3, &TIM_OCInitStructure);
TIM_Cmd(TIM3, ENABLE);
TIM_ITConfig(TIM3, TIM_IT_CC1 | TIM_IT_CC2, ENABLE);
/*
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure); */
}
主程序
/*
因为PLUS1和PLUS2不同步且频率不同,所以只能分别进行捕获,具体方法是分别将两次相邻的捕获值相减得到周期值。
TIM2使用的是向上计数模式,当计数值溢出时必须对捕获值特殊处理。
同样,分频方波和倍频方波输出频率也不同,也只能分别进行比较,具体方法是当比较匹配时输出翻转,
并分别将比较值增加半个周期值,当比较溢出时必须对比较值特殊处理。
*/
#include "stm32f10x.h"
#include "lcd.h"
#include "i2c.h"
#include "init.h"
#include "stdio.h"
#define TIM_CK 1000000
u32 TimingDelay = 0;
void Delay_Ms(u32 nTime);
void Key_Scan(void);
void ADC_Read(void);
unsigned int ADC_Conv(void);
unsigned int ADC_InjeConv(void);
void TIM2_Proc(void);
void TIM3_Proc(void);
void LED_Disp(u16 led);
float ao1,ao2;
u8 string[20];
unsigned long ulIc1,ulIc2,ulOc1,ulOc2;
unsigned int uiId1,uiId2;
unsigned char ucDiv,ucMul;
unsigned long ulTick_ms=0,ulSec=0,ulSec1=0;
u8 shezhi=0,qie=0;
u16 led=0;
//Main Body
int main(void)
{
LCD_Init();
GPIO_Int();
i2c_init();
TIM2_ICInit();
TIM3_OCInit();
Delay_Ms(5);
if(I2C_Read(0x20)!=20)
{
Delay_Ms(5);
I2C_Write(0x20,20);
Delay_Ms(5);
I2C_Write(0x00,1);
Delay_Ms(5);
I2C_Write(0x01,1);
}
Delay_Ms(5);
ucDiv=I2C_Read(0x00);
Delay_Ms(5);
ucMul=I2C_Read(0x01);
while(1)
{
Key_Scan();
ADC_Read();
TIM2_Proc();
TIM3_Proc();
LED_Disp(led);
}
}
void Key_Scan(void)
{
if(RB1==0)
{
Delay_Ms(5);
if(RB1==0)
{
if(shezhi==0)
{
shezhi=1;
LCD_DisplayStringLine(Line0," Setting ");
sprintf((char*)string," DIV : %1d ",ucDiv);
LCD_DisplayStringLine(Line2,string);
sprintf((char*)string," MUL : %1d ",ucMul);
LCD_DisplayStringLine(Line4,string);
LCD_DisplayStringLine(Line6," ");
LCD_DisplayStringLine(Line8," ");
LCD_DisplayStringLine(Line9," 2");
}
else if(shezhi==1)
{
shezhi=0;
Delay_Ms(5);
I2C_Write(0x00,ucDiv);
Delay_Ms(5);
I2C_Write(0x01,ucMul);
}
}while(!RB1);
}
else if(RB2==0)
{
Delay_Ms(5);
if(RB2==0)
{
if(shezhi==1)
{
if(qie==0||qie==2)
{
qie=1;
LCD_SetTextColor(Red);
sprintf((char*)string," DIV : %1d ",ucDiv);
LCD_DisplayStringLine(Line2,string);
LCD_SetTextColor(White);
sprintf((char*)string," MUL : %1d ",ucMul);
LCD_DisplayStringLine(Line4,string);
}
else if(qie==1)
{
qie=2;
LCD_SetTextColor(Red);
sprintf((char*)string," MUL : %1d ",ucMul);
LCD_DisplayStringLine(Line4,string);
LCD_SetTextColor(White);
sprintf((char*)string," DIV : %1d ",ucDiv);
LCD_DisplayStringLine(Line2,string);
}
}
}while(!RB2);
}
else if(RB3==0)
{
Delay_Ms(5);
if(RB3==0)
{
if(shezhi==1)
{
if(qie==1)
{
if(ucDiv<4)ucDiv++;
LCD_SetTextColor(Red);
sprintf((char*)string," DIV : %1d ",ucDiv);
LCD_DisplayStringLine(Line2,string);
LCD_SetTextColor(White);
}
else if(qie==2)
{
if(ucMul<4)ucMul++;
LCD_SetTextColor(Red);
sprintf((char*)string," MUL : %1d ",ucMul);
LCD_DisplayStringLine(Line4,string);
LCD_SetTextColor(White);
}
}
}while(!RB3);
}
else if(RB4==0)
{
Delay_Ms(5);
if(RB4==0)
{
if(shezhi==1)
{
if(qie==1)
{
if(ucDiv>1)ucDiv--;
LCD_SetTextColor(Red);
sprintf((char*)string," DIV : %1d ",ucDiv);
LCD_DisplayStringLine(Line2,string);
LCD_SetTextColor(White);
}
else if(qie==2)
{
if(ucMul>1)ucMul--;
LCD_SetTextColor(Red);
sprintf((char*)string," MUL : %1d ",ucMul);
LCD_DisplayStringLine(Line4,string);
LCD_SetTextColor(White);
}
}
}while(!RB4);
}
}
void Delay_Ms(u32 nTime)
{
TimingDelay = nTime;
while(TimingDelay != 0);
}
unsigned int ADC_Conv(void)
{
/* Start ADC1 Software Conversion */
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));
return ADC_GetConversionValue(ADC1);
}
unsigned int ADC_InjeConv(void)
{
/* Start ADC1 Software Conversion */
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
ADC_SoftwareStartInjectedConvCmd(ADC1, ENABLE);
while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_JEOC));
ADC_ClearFlag(ADC1,ADC_FLAG_JEOC);
return ADC_GetInjectedConversionValue(ADC1,ADC_InjectedChannel_1);
}
void ADC_Read(void)
{
if(shezhi==0)
{
if(ulSec1!=ulSec)
{
ulSec1=ulSec;
LCD_DisplayStringLine(Line0," Measure ");
ao1=ADC_InjeConv()*3.3/0xfff;
sprintf((char*)string," AO1 : %3.2fV ",ao1);
LCD_DisplayStringLine(Line6,string);
ao2=ADC_Conv()*3.3/0xfff;
sprintf((char*)string," AO2 : %3.2fV ",ao2);
LCD_DisplayStringLine(Line8,string);
sprintf((char*)string," %5dHz /%1d %5dHz ",TIM_CK/uiId1,ucDiv,TIM_CK/uiId1/ucDiv);
LCD_DisplayStringLine(Line2,string);
sprintf((char*)string," %5dHz *%1d %5dHz ",TIM_CK/uiId2,ucMul,TIM_CK/uiId2*ucMul);
LCD_DisplayStringLine(Line4,string);
LCD_DisplayStringLine(Line9," 1");
}
}
}
void SysTick_Handler(void)
{
TimingDelay--;
ulTick_ms++;
if(ulTick_ms%1000==0)
ulSec++;
if(shezhi==0)
led&=0xfe;
else
led|=0x01;
if(ao1>ao2)
led|=0x80;
else
led&=0x7f;
}
void TIM2_Proc(void)
{
unsigned long ic;
if(TIM_GetFlagStatus(TIM2, TIM_FLAG_CC2) == SET)
{
ic=ulIc1;
ulIc1=TIM_GetCapture2(TIM2);
if(ulIc1>ic)
uiId1=ulIc1-ic;
else
uiId1=65536+ulIc1-ic;
}
if(TIM_GetFlagStatus(TIM2, TIM_FLAG_CC3) == SET)
{
ic=ulIc2;
ulIc2=TIM_GetCapture3(TIM2);
if(ulIc2>ic)
uiId2=ulIc2-ic;
else
uiId2=65536+ulIc2-ic;
}
}
void TIM3_Proc(void)
{
if (TIM_GetFlagStatus(TIM2, TIM_FLAG_CC1) != RESET)
{
ulOc1+=uiId1*ucDiv>>1;
if(ulOc1>65535)
ulOc1-=65536;
TIM_SetCompare1(TIM3, ulOc1);
TIM_ClearFlag(TIM3,TIM_FLAG_CC1);
}
if (TIM_GetFlagStatus(TIM2, TIM_FLAG_CC2) != RESET)
{
ulOc2+=uiId2/ucMul>>1;
if(ulOc2>65535)
ulOc2-=65536;
TIM_SetCompare2(TIM3, ulOc2);
TIM_ClearFlag(TIM3,TIM_FLAG_CC2);
}
}
void LED_Disp(u16 led)
{
GPIO_Write(GPIOC,~led<<8);
GPIO_SetBits(GPIOD,GPIO_Pin_2);
GPIO_ResetBits(GPIOD,GPIO_Pin_2);
}