(本篇博客有很多还没讲解很细致,先贴出代码,等有时间再进行注解)
设计一个电压测量与方波信号输出设备,设备能检测模拟信号输入,并根据检测到的电压值,计算出两路异相方波信号的相位差,输出信号频率可通过按键调整,设备硬件部分主要由电源部分、控制器单元、按键部分、存储单元和显示部分组成,系统框图如图 1 所示:
CT117E 考试板电路原理图、I2C 总线驱动程序、LCD 驱动程序及本题涉及到的芯片资料可参考计算机上的电子文档。电路原理图、程序流程图及相关工程文件请以考生准考证命名,并保存在指定文件夹中(文件夹名为考生准考证号,文件夹位于 Windows 桌面上)。
设计任务及要求
1. ADC 测量
使用 STM32 处理器片内 ADC 采集电位器 R37 输出电压,记为 Vo,并通过 LCD 显示电压值,保留小数点后两位有效数字。
2. 异相方波输出
使用 STM32 处理器 TIM3 通道(PA6、PA7)输出异相方波信号,PA7 输出信号相对于PA6 滞后相位差(D)与电位器输出电压之间的关系为 D = (Vo/3.3)*360°,通过按键控制信号启动、停止及调节信号输出频率。
3. 按键设置
“B1”按键设定为“启动/停止”按键,切换信号输出状态:“启动”状态下,根据ADC采集到的电压值输出异相方波信号,指示灯 LD1点亮,“停止”状态下,两路输出通道 PA6、PA7 持续输出低电平,指示灯 LD1 熄灭。LCD 实时显示采集电压、信号输出状态和信号参数,显示界面如图 2 所示
“B2”按键设定为“设置”按键,按下后,进入设置界面如图3所示,此时通过“B3”和“B4”按键调整输出信号频率,可调范围为 1KHz~10KHz,每次按下“B3”按键,频率增加 1KHz,按下“B4”按键,频率减小 1KHz,调整完成后,再次按下“B2”按键,保存
信号输出频率参数到 E2PROM,并退出设置界面返回图 2 所示界面。
说明:“B3”和“B4”按键仅在设置界面下有效;设备默认输出信号频率 1KHz。
4. EEPROM 存储
用于存储配置的输出信号频率参数,设备重启后,能够恢复最近一次的配置。
需要完成的要求:
1. 电压测量功能实现;
2. E2PROM 配置存储功能实现;
3. LED 指示功能实现;
4. LCD 显示与界面切换功能实现;
5. 按键切换与控制功能实现;
6. 异相方波信号输出与频率调整功能实现。
u32 TimingDelay = 0;
u8 string[20];
float ADC_Val;
u8 KEY_Flag = 0;
u8 ADC_Flag = 0;
u8 Display_Flag = 0;
u8 LED_Flag = 0;
u16 Deg;
u16 Deg_Last;
extern u8 Set_Flag;
extern u16 LED_MODE;
extern u8 ENABLE_Flag;
extern u16 Frequency;
void Delay_Ms(u32 nTime);
STM3210B_LCD_Init();
LCD_Clear(Blue);
LCD_SetBackColor(Blue);
LCD_SetTextColor(White);
SysTick_Config(SystemCoreClock/1000);
i2c_init();
ADC1_Init();
Frequency = _24c02_Read(0x88) * 1000;
TIM3_Output_Init(Frequency,Deg,1,ENABLE_Flag);
LED_Init();
KEY_Init();
if(KEY_Flag)
{
KEY_Flag = 0;
KEY_Read();
}
void KEY_Read(void)
{
static u16 key1_sum = 0,key2_sum = 0,key3_sum = 0,key4_sum = 0;
//KEY1
if(KEY1 == 0)
{
key1_sum++;
if(key1_sum == 1)
{
ENABLE_Flag ^= 1;
TIM3_Output_Init(Frequency,Deg,0,ENABLE_Flag);
}
}else
{
key1_sum = 0;
}
//KEY2
if(KEY2 == 0)
{
key2_sum++;
if(key2_sum == 1)
{
Set_Flag ^= 1;
LCD_ClearLine(Line0);
LCD_ClearLine(Line2);
LCD_ClearLine(Line3);
LCD_ClearLine(Line4);
LCD_ClearLine(Line5);
LCD_ClearLine(Line6);
LCD_ClearLine(Line7);
LCD_ClearLine(Line8);
LCD_ClearLine(Line9);
LCD_ClearLine(Line1);
if(!Set_Flag)
{
_24c02_Write(0x88,Frequency / 1000);
}
}
}else
{
key2_sum = 0;
}
//KEY3
if((KEY3 == 0) && Set_Flag)
{
key3_sum++;
if(key3_sum == 1)
{
Frequency += 1000;
if(Frequency > 10000) Frequency = 10000;
TIM3_Output_Init(Frequency,Deg,0,ENABLE_Flag);
}
}else
{
key3_sum = 0;
}
//KEY4
if((KEY4 == 0) && Set_Flag)
{
key4_sum++;
if(key4_sum == 1)
{
Frequency -= 1000;
if(Frequency < 1000) Frequency = 1000;
TIM3_Output_Init(Frequency,Deg,0,ENABLE_Flag);
}
}else
{
key4_sum = 0;
}
}
if(ADC_Flag)
{
ADC_Flag = 0;
ADC_Val = Get_Adc(8) * 3.3 / 4096;
Deg = (ADC_Val / 3.3) * 360.0;
TIM3_Output_Init(Frequency,Deg,0,ENABLE_Flag);
}
if(Display_Flag)
{
Display_Flag = 0;
if(!Set_Flag)
{
sprintf((char*)string,"ADC:%.2f ",ADC_Val);
LCD_DisplayStringLine( Line1, string);
if(ENABLE_Flag)
{
LCD_DisplayStringLine( Line3, (u8*)"Output: ON");
}else
{
LCD_DisplayStringLine( Line3, (u8*)"Output:OFF");
}
sprintf((char*)string,"Phase:%d(deg) ",Deg);
LCD_DisplayStringLine( Line5, string);
sprintf((char*)string,"Frequency:%dKHZ ",Frequency / 1000);
LCD_DisplayStringLine( Line7, string);
}else
{
LCD_DisplayStringLine( Line3, (u8*)" Setting ");
sprintf((char*)string," Frequency:%dKHZ ",Frequency / 1000);
LCD_DisplayStringLine( Line7, string);
}
}
if(LED_Flag)
{
LED_Flag = 0;
if(ENABLE_Flag)
{
LED_MODE &=~(1<<8);
}else
{
LED_MODE |= (1<<8);
}
GPIOC->ODR = LED_MODE;
GPIOD->ODR |= (1<<2);
GPIOD->ODR &=~(1<<2);
}
extern u16 CH_Val;
extern u8 KEY_Flag;
extern u8 Display_Flag;
extern u8 ADC_Flag;
extern u8 LED_Flag;
void SysTick_Handler(void)
{
static u8 key_sum = 0;
static u16 adc_sum = 0;
static u8 display_sum = 0;
static u8 led_sum = 0;
TimingDelay--;
if(++led_sum == 100)
{
led_sum = 0;
LED_Flag = 1;
}
if(++key_sum == 50) // 50ms
{
key_sum = 0;
KEY_Flag = 1;
}
if(++adc_sum == 1000)
{
adc_sum = 0;
ADC_Flag = 1;
}
if(++display_sum == 200)
{
display_sum = 0;
Display_Flag = 1;
}
}
void TIM3_IRQHandler(void)
{
u16 capture;
if(TIM_GetITStatus(TIM3, TIM_IT_CC1) == 1)
{
TIM_ClearITPendingBit( TIM3, TIM_IT_CC1);
capture = TIM_GetCapture1(TIM3);
TIM_SetCompare1(TIM3, capture + CH_Val * 0.5);
}
if(TIM_GetITStatus(TIM3, TIM_IT_CC2) == 1)
{
TIM_ClearITPendingBit( TIM3, TIM_IT_CC2);
capture = TIM_GetCapture2(TIM3);
TIM_SetCompare2(TIM3, capture + CH_Val * 0.5);
}
}
#include "IO.h"
u16 CH_Val;
u16 LED_MODE = 0xffff;
u8 ENABLE_Flag = 1;
u16 Frequency = 3000;
u8 Set_Flag = 0;
extern u16 Deg;
/////////////////////// 24c02 /////////////////
void _24c02_Write(u8 address,u8 data)
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(address);
I2CWaitAck();
I2CSendByte(data);
I2CWaitAck();
I2CStop();
}
u8 _24c02_Read(u8 address)
{
u8 temp;
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(address);
I2CWaitAck();
I2CStart();
I2CSendByte(0xa1);
I2CWaitAck();
temp = I2CReceiveByte();
I2CWaitAck();
I2CStop();
return temp;
}
///////////////////// ADC //////////////////////
void ADC1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_ADC1,ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
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_Cmd(ADC1, ENABLE);
ADC_ResetCalibration( ADC1);
while(ADC_GetResetCalibrationStatus( ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
}
u16 Get_Adc(u8 Channel)
{
u16 temp;
ADC_RegularChannelConfig( ADC1,Channel, 1,ADC_SampleTime_239Cycles5);
ADC_SoftwareStartConvCmd(ADC1,ENABLE);
while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == 0);
temp = ADC_GetConversionValue(ADC1);
ADC_SoftwareStartConvCmd(ADC1,DISABLE);
return temp;
}
/////////////////////// PWM_Output ///////////////////////
void TIM3_Output_Init(u16 fre,u16 deg,u8 status,u8 enable)
{
u16 phase;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
if(status)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA ,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3 ,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
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);
TIM_TimeBaseInitStructure.TIM_Period = 0xffff;
TIM_TimeBaseInitStructure.TIM_Prescaler = 71;
TIM_TimeBaseInitStructure.TIM_CounterMode = 0x0;
TIM_TimeBaseInitStructure.TIM_ClockDivision = 0x0;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
}
CH_Val = 1000000 / fre;
phase = CH_Val * deg / 360;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
if(enable)
{
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
}else
{
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable;
}
TIM_OCInitStructure.TIM_Pulse = CH_Val;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
if(enable)
{
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
}else
{
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable;
}
TIM_OCInitStructure.TIM_Pulse = CH_Val;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OC2Init(TIM3, &TIM_OCInitStructure);
TIM_SetCounter(TIM3, 0X0);
TIM_SetCompare1(TIM3, 0X0);
TIM_SetCompare2(TIM3, phase);
TIM_Cmd(TIM3,ENABLE);
TIM_ITConfig( TIM3, TIM_IT_CC1 | TIM_IT_CC2,ENABLE);
}
/////////////////// LED ///////////////////////////
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = 0XFF00;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIOC->ODR = 0XFFFF;
GPIOD->ODR |= (1<<2);
GPIOD->ODR &=~(1<<2);
}