蓝桥杯嵌入式开发经验分享(第六届模拟——“双通道方波频率检测与倍频输出”)

2019-04-13 11:12发布

作者:马一飞                                                         QQ:791729359       

在学习过程中有什么问题可以联系

(本篇博客有很多还没讲解很细致,先贴出代码,等有时间再进行注解)

一、题目

        “双通道方波频率检测与倍频输出”设计要求测量输入方波信号的频率,并根据设定的倍频数,输出经过倍频的方波信号。倍频数可以通过按键设定,也可以通过串行口设定;LCD显示 2 个通道的频率测量值和倍频数。系统框图如图 1 所示:                                                                                                                                                              图1.  系统框图 CT117E 考试板电路原理图、LCD 驱动程序、及本题涉及到的芯片资料可参考计算机上的电子文档。电路原理图、程序流程图及相关工程文件请以考生准考证命名,并保存在指定文件夹中(文件夹名为考生准考证号,文件夹位于 Windows 桌面上)。 设计任务及要求 1. 频率测量和倍频输出         输入通道 1 为 PA1,相应的倍频输出通道为 PA6;输入通道 2 为 PA2,相应的倍频输出通道为 PA7。输入信号频率范围为 50Hz 到 50KHz;输入信号超出范围时,输出为低电平。
2. 按键功能         定义 4 个按键“K1”、“K2”、“K3”、“K4”,其中:
       “K1”按键:用于切换“本地设定”和“串口设定”。当处于本地设定时,下面的“K2”、
       “K3”、“K4”按键功能才有效;
       “K2”按键:用于在两个通道之间来回切换;
       “K3”按键:对当前通道的倍频数减 1,减到 1 时停止减数;
       “K4”按键:对当前通道的倍频数加 1,加到 10 时停止加数; 3. LED 指示功能
       定义 3 个 LED 指示灯,“LED1”到“LED3”,其中:
       当通道 1 有输出时,“LED1”点亮,否则熄灭;
       当通道 2 有输出时,“LED2”点亮,否则熄灭;
       当系统处于“串口设定”方式时,“LED3”点亮,否则熄灭。
4. EEPROM 存储
       EEPROM 用于存储 2 路通道的倍频数,数据在 EEPROM 中的存储格式自行定义,2 路通道的默认值为 2。
5. LCD 显示单元
       LCD 显示 2 个通道的测量频率、相应的倍频数和当前设定通道号,显示格式可参考图 2:
       其中:
              Channel(1):通道号
              N(1):倍频数
              右下角的数字 1 表示设定时的当前通道号。                                                                                                                                                           图 2 液晶显示界面参考图 6. 串行设定功能
       当系统处于“串口设定”方式时,可通过串口设定 2 个通道的倍频数,格式如下:
              SET:x:yy
              其中:SET :设定标志;x:通道号,1 或 2;yy:倍频数,2 到 10。
       串口工作方式为:9600 波特,数据位 8,停止位 1,无校验位。
7. 电路设计
       使用基本逻辑电路及阻容元件设计一个硬件四倍频电路,使得输出方波信号的频率是输入方波信号频率的 4 倍

二、模块化代码分析

1、初始化部分

u32 TimingDelay = 0; extern u16 TIM3_Ch1_Val; extern u16 TIM3_Ch2_Val; extern u16 LED_MODE; extern u8 Channal_1_N; extern u8 Channal_2_N; extern u8 Channal_Flag; extern u8 Set_Flag; u16 capture; u32 TIM2_CH2_CAPTURE_HL = 0; u8 TIM2_CH2_CAPTURE_MODE = 0; u32 TIM2_CH3_CAPTURE_HL = 0; u8 TIM2_CH3_CAPTURE_MODE = 0; u8 Channal_1_Enable = 1; u8 Channal_2_Enable = 1; u32 Channal_1_Frequency; u32 Channal_2_Frequency; u8 CAPTURE_Flag = 0; u8 KEY_Flag = 0; u8 OUTPUT_Flag = 0; u8 Display_Flag = 0; u8 string[20]; u8 LED_Flag = 0; u8 RXCUNT = 0; u8 RXOVER = 0; u8 RX_BUF[20]; u8 i; void Delay_Ms(u32 nTime); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); STM3210B_LCD_Init(); LCD_Clear(Blue); LCD_SetBackColor(Blue); LCD_SetTextColor(White); SysTick_Config(SystemCoreClock/1000); i2c_init(); Channal_1_N = _24c02_Read(0x01); Delay_Ms(10); Channal_2_N = _24c02_Read(0x11); TIM3_OUTPUT_Init(5000,10000,1,1,1); TIM2_CAPTURE_Init(); KEY_Init(); LED_Init(); TIM1_PWM_Init(); USART2_Init(9600);

2、按键部分

if(KEY_Flag) { KEY_Read(); KEY_Flag = 0; } void KEY_Read(void) { static u16 key1_sum,key2_sum,key3_sum,key4_sum; //KEY1 if(KEY1 == 0) { key1_sum++; if(key1_sum == 1) { Set_Flag ^= 1; } }else { key1_sum = 0; } //KEY2 if(KEY2 == 0) { key2_sum++; if((key2_sum == 1) && (Set_Flag == 0)) { Channal_Flag ^= 1; } }else { key2_sum = 0; } //KEY3 if(KEY3 == 0) { key3_sum++; if((key3_sum == 1) && (Set_Flag == 0)) { if(!Channal_Flag) { Channal_1_N++; }else { Channal_2_N++; } _24c02_Write(0x01,Channal_1_N); Delay_Ms(10); _24c02_Write(0x11,Channal_2_N); } }else { key3_sum = 0; } //KEY4 if(KEY4 == 0) { key4_sum++; if((key4_sum == 1) && (Set_Flag == 0)) { if(!Channal_Flag) { Channal_1_N--; }else { Channal_2_N--; } if(Channal_1_N < 1) Channal_1_N = 1; if(Channal_2_N < 1) Channal_2_N = 1; _24c02_Write(0x01,Channal_1_N); Delay_Ms(10); _24c02_Write(0x11,Channal_2_N); } }else { key4_sum = 0; } }

3、捕获部分

if(TIM2_CH2_CAPTURE_MODE == 2) { Channal_1_Frequency = 1000000 / TIM2_CH2_CAPTURE_HL; if((Channal_1_Frequency < 50) || (Channal_1_Frequency > 50000)) { Channal_1_Enable = 0; }else { Channal_1_Enable = 1; } TIM2_CH2_CAPTURE_MODE = 0; } if(TIM2_CH3_CAPTURE_MODE == 2) { Channal_2_Frequency = 1000000 / TIM2_CH3_CAPTURE_HL; if((Channal_2_Frequency < 50) || (Channal_2_Frequency > 50000)) { Channal_2_Enable = 0; }else { Channal_2_Enable = 1; } TIM2_CH3_CAPTURE_MODE = 0; }

4、输出改变

if(OUTPUT_Flag) { TIM3_OUTPUT_Init(Channal_1_Frequency * Channal_1_N,Channal_2_Frequency * Channal_2_N,0,Channal_1_Enable,Channal_2_Enable); OUTPUT_Flag = 0; }

5、LCD显示部分

if(Display_Flag) { sprintf((char*)string," Channel(1):%dHZ ",Channal_1_Frequency); LCD_DisplayStringLine(Line2, string); sprintf((char*)string," N(1):%d ",Channal_1_N); LCD_DisplayStringLine(Line3, string); sprintf((char*)string," Channel(2):%dHZ ",Channal_2_Frequency); LCD_DisplayStringLine(Line4, string); sprintf((char*)string," N(2):%d ",Channal_2_N); LCD_DisplayStringLine(Line5, string); sprintf((char*)string," %d ",Channal_Flag + 1); LCD_DisplayStringLine(Line8, string); Display_Flag = 0; }

6、LED显示

if(LED_Flag) { if(Set_Flag) { LED_MODE &=~(1<<10); }else { LED_MODE |= (1<<10); } if(Channal_1_Frequency) { LED_MODE &=~(1<<8); }else { LED_MODE |= (1<<8); } if(Channal_2_Frequency) { LED_MODE &=~(1<<9); }else { LED_MODE |= (1<<9); } GPIOC->ODR = LED_MODE; GPIOD->ODR |= (1<<2); GPIOD->ODR &=~(1<<2); LED_Flag = 0; }

7、串口接收部分

if(RXOVER) { // USART2_SendString(RX_BUF); if(Set_Flag == 1) { if((RX_BUF[4] - 0X30) == 1) { Channal_1_N = (RX_BUF[6] - 0X30) * 10 + (RX_BUF[7] - 0X30); } if((RX_BUF[4] - 0X30) == 2) { Channal_2_N = (RX_BUF[6] - 0X30) * 10 + (RX_BUF[7] - 0X30); } } for(i=0;i<20;i++) { RX_BUF[i] = 0; } USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); RXOVER = 0; }

8、滴答定时器及中断部分

void TIM3_IRQHandler(void) { if(TIM_GetITStatus(TIM3, TIM_IT_CC1) == 1) { TIM_ClearITPendingBit(TIM3, TIM_IT_CC1); capture = TIM_GetCapture1(TIM3); TIM_SetCompare1(TIM3,capture + TIM3_Ch1_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 + TIM3_Ch2_Val * 0.5); } } void TIM2_IRQHandler(void) { if(TIM_GetITStatus(TIM2, TIM_IT_CC2) == 1) { TIM_ClearITPendingBit(TIM2, TIM_IT_CC2); if(!CAPTURE_Flag) { switch(TIM2_CH2_CAPTURE_MODE) { case 0: TIM2_CH2_CAPTURE_HL = 0; TIM2_CH2_CAPTURE_MODE = 1; TIM_SetCounter(TIM2,0x0); break; case 1: TIM2_CH2_CAPTURE_HL = TIM_GetCounter(TIM2); TIM2_CH2_CAPTURE_MODE = 2; break; default:break; } }else { TIM2_CH2_CAPTURE_MODE = 0; } } if(TIM_GetITStatus(TIM2, TIM_IT_CC3) != RESET) { TIM_ClearITPendingBit(TIM2, TIM_IT_CC3); if(CAPTURE_Flag) { switch(TIM2_CH3_CAPTURE_MODE) { case 0: TIM2_CH3_CAPTURE_HL = 0; TIM2_CH3_CAPTURE_MODE = 1; TIM_SetCounter(TIM2,0x0); break; case 1: TIM2_CH3_CAPTURE_HL = TIM_GetCounter(TIM2); TIM2_CH3_CAPTURE_MODE = 2; break; default:break; } }else { TIM2_CH3_CAPTURE_MODE = 0; } } } void USART2_IRQHandler(void) { u8 temp; if(USART_GetITStatus(USART2,USART_IT_RXNE) == 1) { USART_ClearITPendingBit(USART2,USART_IT_RXNE); temp = USART_ReceiveData(USART2); if(temp == ' ') { RXCUNT = 0; RXOVER = 1; USART_ITConfig(USART2, USART_IT_RXNE, DISABLE); }else { RX_BUF[RXCUNT] = temp; RXCUNT++; } } } void SysTick_Handler(void) { static u8 CAPTURE_sum = 0; static u8 KEY_sum = 0; static u16 OUTPUT_sum = 0; static u8 Display_sum = 0; static u8 LED_sum = 0; TimingDelay--; if(++CAPTURE_sum == 200) // 200ms { CAPTURE_sum = 0; CAPTURE_Flag ^= 1; } if(++KEY_sum == 50) //50ms { KEY_sum = 0; KEY_Flag = 1; } if(++OUTPUT_sum == 1000)// 1s { OUTPUT_sum = 0; OUTPUT_Flag = 1; } if(++Display_sum == 100) // 100ms { Display_sum = 0; Display_Flag = 1; } if(++LED_sum == 50) //50ms { LED_sum = 0; LED_Flag = 1; } }

三、通用初始化部分

#include "IO.h" u16 TIM3_Ch1_Val; u16 TIM3_Ch2_Val; u16 LED_MODE = 0XFFFF; u8 Set_Flag = 0; u8 Channal_Flag = 0; u8 Channal_1_N = 1; u8 Channal_2_N = 1; //////////////////// 24c02 ///////////////////// u8 _24c02_Read(u8 address) { u8 data; I2CStart(); I2CSendByte(0xa0); I2CWaitAck(); I2CSendByte(address); I2CWaitAck(); I2CStart(); I2CSendByte(0xa1); I2CWaitAck(); data = I2CReceiveByte(); I2CWaitAck(); I2CStop(); return data; } void _24c02_Write(u8 address,u8 data) { I2CStart(); I2CSendByte(0xa0); I2CWaitAck(); I2CSendByte(address); I2CWaitAck(); I2CSendByte(data); I2CWaitAck(); I2CStop(); } //////////////////// TIM3 ±¶ÆµÊä³ö²¿·Ö ///////////////////// void TIM3_OUTPUT_Init(u16 ch2_fre,u16 ch3_fre,u8 status,u8 Ch1_Enable,u8 Ch2_Enable) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; NVIC_InitTypeDef NVIC_InitStructure; 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_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); TIM_TimeBaseInitStructure.TIM_Period = 0xffff; TIM_TimeBaseInitStructure.TIM_Prescaler = 71; TIM_TimeBaseInitStructure.TIM_ClockDivision = 0x0; TIM_TimeBaseInitStructure.TIM_CounterMode = 0x0; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure); 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); } TIM3_Ch1_Val = 1000000 / ch2_fre; TIM3_Ch2_Val = 1000000 / ch3_fre; TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; if(Ch1_Enable) { TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; }else { TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable; } TIM_OCInitStructure.TIM_Pulse = TIM3_Ch2_Val; TIM_OC1Init(TIM3,&TIM_OCInitStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; if(Ch2_Enable) { TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; }else { TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable; } TIM_OCInitStructure.TIM_Pulse = TIM3_Ch2_Val; TIM_OC2Init(TIM3,&TIM_OCInitStructure); TIM_SetCompare1(TIM3, 0x0); TIM_SetCompare2(TIM3, 0x0); TIM_Cmd(TIM3, ENABLE); TIM_ITConfig(TIM3, TIM_IT_CC1 | TIM_IT_CC2, ENABLE); } ///////////////////// ²âÊÔ·½²¨ //////////////// void TIM1_PWM_Init(void) { u16 fre; GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_TIM1, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); fre = 1000000 / 2000; TIM_TimeBaseInitStructure.TIM_Period = fre - 1; TIM_TimeBaseInitStructure.TIM_Prescaler = 71; TIM_TimeBaseInitStructure.TIM_ClockDivision = 0x0; TIM_TimeBaseInitStructure.TIM_CounterMode = 0x0; TIM_TimeBaseInit(TIM1, &TIM_TimeBaseInitStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = (fre - 2) * 0.5; TIM_OC2Init(TIM1,&TIM_OCInitStructure); TIM_CtrlPWMOutputs( TIM1,ENABLE); TIM_Cmd(TIM1, ENABLE); } ////////////////////// TIM2 ²¶»ñ²¿·Ö //////////////// void TIM2_CAPTURE_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; NVIC_InitTypeDef NVIC_InitStructure; TIM_ICInitTypeDef TIM_ICInitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); TIM_TimeBaseInitStructure.TIM_Period = 0xffff; TIM_TimeBaseInitStructure.TIM_Prescaler = 71; TIM_TimeBaseInitStructure.TIM_ClockDivision = 0x0; TIM_TimeBaseInitStructure.TIM_CounterMode = 0x0; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure); NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); TIM_ICInitStructure.TIM_Channel = TIM_Channel_2; TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM_ICInitStructure.TIM_ICFilter = 0x0; TIM_ICInit(TIM2, &TIM_ICInitStructure); TIM_ICInitStructure.TIM_Channel = TIM_Channel_3; TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM_ICInitStructure.TIM_ICFilter = 0x0; TIM_ICInit(TIM2, &TIM_ICInitStructure); TIM_Cmd(TIM2, ENABLE); TIM_ITConfig(TIM2, TIM_IT_CC3 | TIM_IT_CC2, ENABLE); } ///////////////// °´¼ü²¿·Ö /////////////////////// 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_IPU; 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); } ////////////////////// LED ²¿·Ö /////////////////// void LED_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD, ENABLE); GPIO_InitStructure.GPIO_Pin = 0XFF00; 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_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOD, &GPIO_InitStructure); GPIOC-> ODR = 0XFFFF; GPIOD-> ODR |= (1<<2); GPIOD-> ODR &=~(1<<2); } ////////////// ´®¿Ú²¿·Ö ///////////////////// void USART2_Init(u32 bound) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); // GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; // GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = bound; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx ; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_Init(USART2, &USART_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); USART_Cmd(USART2, ENABLE); USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); } void USART2_SendString(u8 *str) { u8 index = 0; do { USART_SendData(USART2, str[index]); while(USART_GetFlagStatus(USART2,USART_FLAG_TXE) == 0); index++; }while(str[index] != 0); }