完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
一、题目
“双路输出控制器”具有信号输出时间设定、输出信号占空比调整、当前输出通道及时间显示、系统工作参数存储、串口通讯及 LED 指示等功能。“双路输出控制器”通过串口完成信号输出时间设定功能;通过 EEPROM 完成系统工作参数存储功能;通过按键完成输出通道切换、输出信号占空比调整及停止信号输出功能;系统硬件电路主要由 MCU 控制单元、独立按键、LCD 显示单元、串口通讯单元、EEPROM 数据存储单元和 LED 指示单元组成,系统框图如图 1 所示: 设计任务及要求 1. 独立按键功能 1.1 按下 B1 按键,PA1 输出脉宽调制信号,再次按下 B1,PA1 持续输出低电平,如此循环; 1.2 B2 按键功能设定为通道 PA1 输出脉宽调制信号占空比调整,按下 B2,通道 PA1 输出信号占空比以 10%步进,调整后的输出信号占空比将保存至 EEPROM 中; 1.3 按下 B3 按键,PA2 输出脉宽调制信号,再次按下 B3,PA2 持续输出低电平,如此循环; 1.4 B4 按键功能设定为通道 PA2 输出脉宽调制信号占空比调整,按下 B4,通道 PA2 输出信号占空比以 10%步进,调整后的输出信号占空比将保存至 EEPROM 中。 2. 串口通讯单元 系统可通过串口接收命令,用户输入字符串“hh:mm:ss-PAx-yS”,设定 PAx 通道在 hh时 mm 分 ss 秒输出脉宽调制信号,持 续输出 y 秒(0 [命令格式举例] - 通过串口输入“00:00:20-PA1-5S”,即设定系统在 0 时 0 分 20 秒通过 PA1 通道持续输出脉宽调制信号,5 秒后输出低电平信号。 3. LCD 显示单元 通过 LCD 显示当前 EEPROM 中存储的脉宽调制信号占空比、系统时间、当前正在输出的通道以及通过串口接收到的命令,LCD 显示界面参考示意图如图 2、图 3 所示: 4. EEPROM 数据存储单元 通过 EEPROM 存储 PA1、PA2 输出信号的占空比,占空比数值可以通过按键调整。 5. LED 指示功能 通道 PA1 输出脉宽调制信号时,指示灯 LD1 点亮,其余指示灯处于熄灭状态; 通道 PA2 输出脉宽调制信号时,指示灯 LD2 点亮,其余指示灯处于熄灭状态。 6. 系统工作及初始化状态说明 系统初始化时间设定为 23 时 59 分 50 秒,PA1、PA2 输出频率固定为 1KHz,串口通讯波特率设定为 9600 bps。 二、模块化代码分析 1、初始化部分 #include "stm32f10x.h" #include "lcd.h" #include "stdio.h" #include "i2c.h" #include "IO.h" u32 TimingDelay = 0; u8 RXCUNT = 0; u8 RXOVER = 0; u8 RXBUF[20]; u8 i; u8 key_Flag = 0; u8 string[20]; u8 RTC_Read = 0; u32 TimeVal; u8 hour,min,sec; u8 RX_hour,RX_min,RX_sec,RX_ch,RX_delay; u8 LED_Flag = 0; u8 A1_Duty = 10,A2_Duty = 10; extern u8 CH2_OutPut,CH3_OutPut; extern u16 LED_MODE; 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(); USART2_Init(9600); LED_Init(); KEY_Init(); RTC_Init(23,59,55); A1_Duty = _24c02_read(0xaa); A2_Duty = _24c02_read(0xbb); TIM2_PA1_PWM_Init(A1_Duty,A2_Duty,1,0,0); LCD_DisplayStringLine(Line9, "None"); LCD_DisplayStringLine(Line8, " Command : "); 2、串口部分 if(RXOVER == 1) { //USART2_SendString(RXBUF); RX_hour =(RXBUF[0] - 0x30) * 10 + (RXBUF[1] - 0x30); RX_min = (RXBUF[3] - 0x30) * 10 + (RXBUF[4] - 0x30); RX_sec = (RXBUF[6] - 0x30) * 10 + (RXBUF[7] - 0x30); RX_ch = RXBUF[11] - 0x30; LCD_ClearLine(Line9); LCD_DisplayStringLine(Line9, RXBUF); USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); RXOVER = 0; } 3、按键部分 if(key_Flag == 1) // 50ms { KEY_Read(); key_Flag = 0; } void KEY_Read(void) { static u16 key1_sum = 0,key2_sum = 0,key3_sum = 0,key4_sum = 0; if(KEY1 == 0) { key1_sum++; if(key1_sum == 1) { CH2_OutPut ^= 1; TIM2_PA1_PWM_Init(A1_Duty,A2_Duty,0,CH2_OutPut,CH3_OutPut); } }else { key1_sum = 0; } if(KEY2 == 0) { key2_sum++; if(key2_sum == 1) { A1_Duty += 10; if(A1_Duty == 100) { A1_Duty = 10; } _24c02_write(0xaa,A1_Duty); TIM2_PA1_PWM_Init(A1_Duty,A2_Duty,0,CH2_OutPut,CH3_OutPut); } }else { key2_sum = 0; } if(KEY3 == 0) { key3_sum++; if(key3_sum == 1) { CH3_OutPut ^= 1; TIM2_PA1_PWM_Init(A1_Duty,A2_Duty,0,CH2_OutPut,CH3_OutPut); } }else { key3_sum = 0; } if(KEY4 == 0) { key4_sum++; if(key4_sum == 1) { A2_Duty += 10; if(A2_Duty == 100) { A2_Duty = 10; } _24c02_write(0xbb,A1_Duty); TIM2_PA1_PWM_Init(A1_Duty,A2_Duty,0,CH2_OutPut,CH3_OutPut); } }else { key4_sum = 0; } } 4、RTC部分 if(RTC_Read == 1) { TimeVal = RTC_GetCounter(); hour = TimeVal / 3600; min = TimeVal % 3600 / 60; sec = TimeVal % 3600 % 60; if(TimeVal == (RX_hour * 3600 + RX_min * 60 + RX_sec)) { RX_delay = RXBUF[13] - 0x30; if(RX_ch == 1) { CH2_OutPut = 1; } if(RX_ch == 2) { CH3_OutPut = 1; } TIM2_PA1_PWM_Init(A1_Duty,A2_Duty,0,CH2_OutPut,CH3_OutPut); } if(!RX_delay) { if(RX_ch == 1) { CH2_OutPut = 0; } if(RX_ch == 2) { CH3_OutPut = 0; } TIM2_PA1_PWM_Init(A1_Duty,A2_Duty,0,CH2_OutPut,CH3_OutPut); for(i = 0;i < 20;i++) { RXBUF = 0; } } RTC_Read = 0; } 5、LED部分 if(LED_Flag) { if(CH2_OutPut) { LED_MODE &= ~(1<<8); GPIOC->ODR = LED_MODE; GPIOD->ODR |= (1<<2); GPIOD->ODR &=~(1<<2); }else { LED_MODE |= (1<<8); GPIOC->ODR = LED_MODE; GPIOD->ODR |= (1<<2); GPIOD->ODR &=~(1<<2); } if(CH3_OutPut) { LED_MODE &= ~(1<<9); GPIOC->ODR = LED_MODE; GPIOD->ODR |= (1<<2); GPIOD->ODR &=~(1<<2); }else { LED_MODE |= (1<<9); GPIOC->ODR = LED_MODE; GPIOD->ODR |= (1<<2); GPIOD->ODR &=~(1<<2); } } 6、LCD显示 sprintf((char *)string," PWM-PA1 : %d %% ",A1_Duty); LCD_DisplayStringLine(Line1, string); sprintf((char *)string," PWM-PA2 : %d %% ",A2_Duty); LCD_DisplayStringLine(Line3, string); sprintf((char *)string," TIME : %.2d:%.2d:%.2d ",hour,min,sec); LCD_DisplayStringLine(Line5, string); if(CH2_OutPut && CH3_OutPut) { sprintf((char *)string," Channel : PA1 PA2 "); LCD_DisplayStringLine(Line6, string); }else if(CH2_OutPut) { sprintf((char *)string," Channel : PA1 "); LCD_DisplayStringLine(Line6, string); }else if(CH3_OutPut) { sprintf((char *)string," Channel : PA2 "); LCD_DisplayStringLine(Line6, string); }else { sprintf((char *)string," Channel : "); LCD_DisplayStringLine(Line6, string); } 7、滴答定时器及中断部分 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 == 'n') { RXCUNT = 0; RXOVER = 1; USART_ITConfig(USART2, USART_IT_RXNE, DISABLE); }else { RXBUF[RXCUNT] = temp; RXCUNT++; } } } void RTC_IRQHandler(void) { while(RTC_GetITStatus(RTC_IT_SEC) == 1) { RTC_ClearITPendingBit(RTC_IT_SEC); RTC_Read = 1; if(RTC_GetCounter() == (24 * 3600)) { RTC_SetCounter(0x0); RTC_WaitForLastTask(); } } } void SysTick_Handler(void) { static u8 key_sum = 0; static u16 second_sum = 0; static u8 LED_sum = 0; TimingDelay--; if(++key_sum == 50) //50ms { key_sum = 0; key_Flag = 1; } if(++second_sum == 1000) //1s { second_sum = 0; if(RX_delay) RX_delay--; } if(++LED_sum == 200) // 200ms { LED_sum = 0; LED_Flag = 1; } } 三、通用初始化部分 #include "IO.h" u16 LED_MODE = 0XFFFF; extern u8 A1_Duty,A2_Duty; u8 CH2_OutPut = 0,CH3_OutPut = 0; /// 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(); return temp; } 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_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; // USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_InitStructure.USART_Mode = USART_Mode_Rx; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_Init(USART2,&USART_InitStructure); USART_Cmd(USART2, ENABLE); NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); 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); //} /// 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_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOD, &GPIO_InitStructure); 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); GPIOC->ODR = 0XFFFF; GPIOD->ODR |= (1<<2); GPIOD->ODR &=~(1<<2); } 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_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); } / RTC // void RTC_Init(u8 HH,u8 MM,u8 SS) { NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP | RCC_APB1Periph_PWR, ENABLE); PWR_BackupAccessCmd(ENABLE); BKP_DeInit(); NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); RCC_LSICmd(ENABLE); while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == 0); RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI); RCC_RTCCLKCmd(ENABLE); RTC_WaitForSynchro(); RTC_WaitForLastTask(); RTC_SetPrescaler(40000-1); RTC_WaitForLastTask(); RTC_ITConfig(RTC_IT_SEC, ENABLE); RTC_WaitForLastTask(); RTC_SetCounter(HH * 3600 + MM * 60 + SS); RTC_WaitForLastTask(); } / PWM / void TIM2_PA1_PWM_Init(u8 duty_A1,u8 duty_A2,u8 status,u8 CH2_OPEN,u8 CH3_OPEN) { u32 A1_Pluse,A2_Pluse; GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_OCInitTypeDef TIM_OCInitStructure; if(status) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); TIM_TimeBaseInitStructure.TIM_Period = 999; TIM_TimeBaseInitStructure.TIM_Prescaler = 71; TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure); } A1_Pluse = 998 * duty_A1 / 100; A2_Pluse = 998 * duty_A2 / 100; TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; if(CH2_OPEN) { TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; }else { TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable; } TIM_OCInitStructure.TIM_Pulse = A1_Pluse; TIM_OC2Init(TIM2,&TIM_OCInitStructure); if(CH3_OPEN) { TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; }else { TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable; } TIM_OCInitStructure.TIM_Pulse = A2_Pluse; TIM_OC3Init(TIM2,&TIM_OCInitStructure); if(status) { TIM_Cmd(TIM2,ENABLE); } } |
|
|
|
只有小组成员才能发言,加入小组>>
imx6ull 和 lan8742 工作起来不正常, ping 老是丢包
2780 浏览 0 评论
3351 浏览 9 评论
3030 浏览 16 评论
3525 浏览 1 评论
9131 浏览 16 评论
1258浏览 3评论
647浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
638浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2386浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1950浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-2-2 19:19 , Processed in 1.341524 second(s), Total 79, Slave 59 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号