完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
一、题目
设计一个电压测量与方波信号输出设备,设备能检测模拟信号输入,并根据检测到的电压值,计算出两路异相方波信号的相位差,输出信号频率可通过按键调整,设备硬件部分主要由电源部分、控制器单元、按键部分、存储单元和显示部分组成,系统框图如图 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. 异相方波信号输出与频率调整功能实现。 二、模块化代码分析 1、初始化部分 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(); 2、按键部分 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; } } 3、ADC部分 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); } 4、LCD显示部分 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); } } 5、LED显示 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); } 6、滴答定时器及中断部分 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); } |
|
|
|
只有小组成员才能发言,加入小组>>
3260 浏览 9 评论
2940 浏览 16 评论
3442 浏览 1 评论
8943 浏览 16 评论
4035 浏览 18 评论
1073浏览 3评论
557浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
550浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2285浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1844浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-5 21:30 , Processed in 1.264599 second(s), Total 79, Slave 59 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号