版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本届试题虽说用到的模块较简单,但是逻辑却较为复杂;其中涉及多个变量,才可以将功能完整的实现,笔者也是参考大神程序的。
①、库文件
②、初始化
#include "stm32f10x.h"
#include "lcd.h"
#include <stdio.h>
#include "init.h"
void GPIO_Int(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD , ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB , ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, 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_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);
//KEY
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
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);
//rtc //注意,les全部替换为lsi 否则无法运行
/* Allow access to BKP Domain */
PWR_BackupAccessCmd(ENABLE);
/* Reset Backup Domain */
BKP_DeInit();
/* Enable LSE */
RCC_LSICmd(ENABLE);
/* Wait till LSE is ready */
while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
{}
/* Select LSE as RTC Clock Source */
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
/* Enable RTC Clock */
RCC_RTCCLKCmd(ENABLE);
/* Wait for RTC registers synchronization */
RTC_WaitForSynchro();
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask();
/* Enable the RTC Second */
RTC_ITConfig(RTC_IT_SEC, ENABLE);
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask();
/* Set RTC prescaler: set RTC period to 1sec */
RTC_SetPrescaler(39999);
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask();
RTC_SetCounter(HH*3600+MM*60+SS);
RTC_WaitForLastTask();
NVIC_Configuration();
}
void TIM3_Init(uint16_t Fre,uint16_t CCR1_Val,uint16_t CCR2_Val)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, 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);
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = Fre;
TIM_TimeBaseStructure.TIM_Prescaler = 71;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
/* PWM1 Mode configuration: Channel1 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = CCR1_Val;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
/* PWM1 Mode configuration: Channel2 */
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = CCR2_Val;
TIM_OC2Init(TIM3, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM3, ENABLE);
/* TIM3 enable counter */
TIM_Cmd(TIM3, ENABLE);
}
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Configure one bit for preemption priority */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
/* Enable the RTC Interrupt */
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);
}
void LCD_Init(void)
{
STM3210B_LCD_Init();
LCD_Clear(Blue);
LCD_SetBackColor(Blue);
LCD_SetTextColor(White);
SysTick_Config(SystemCoreClock/1000);
LCD_DisplayStringLine(Line0," ");
LCD_DisplayStringLine(Line1," Now Flat ");
LCD_DisplayStringLine(Line2," ");
LCD_DisplayStringLine(Line3," ");
LCD_DisplayStringLine(Line4," 1 ");
LCD_DisplayStringLine(Line5," 12: 50: 55 ");
LCD_DisplayStringLine(Line6," ");
LCD_DisplayStringLine(Line7," ");
LCD_DisplayStringLine(Line8," ");
LCD_DisplayStringLine(Line9," ");
}
③、中断服务函数
void RTC_IRQHandler(void)
{
if (RTC_GetITStatus(RTC_IT_SEC) != RESET)
{
/* Clear the RTC Second interrupt */
RTC_ClearITPendingBit(RTC_IT_SEC);
/* Enable time update */
TimeDisplay = 1;
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask();
}
}
④、主函数
#include "stm32f10x.h"
#include "lcd.h"
#include <stdio.h>
#include "init.h"
u32 TimingDelay = 0;
__IO uint32_t TimeDisplay = 0;;
u8 string[20];
u8 Flat1=0,Flat2=0,Flat3=0,Flat4=0,Now_Flat=1;
u32 key_ms=100000000;
u16 led=0xffff;
u8 key_flag=1;
u8 Scan_Up_Flag=0,Scan_Down_Flag=0;
u8 Door_State_Flag=1; //默认门是开着的
u8 i=0;
u32 Door_Close_Ms=100000000;
u32 Door_Open_ms=100000000;
u32 Lift_Motor_Ms=100000000;
u8 Door_Closefinish_flag=0;
u8 LED_FlowDown_Flag=0;
u8 LED_FlowUp_Flag=0;
u8 LED_FlowUp_ms=0;
u8 Arrive_Floor_flag=0;
u8 Stop_flag=0;
u32 Door_Wait_ms=1000000;
u8 Door_Wait_flag=0;
u8 LCD_FloorTurn_nTime=0;
u32 LCD_FloorTurn_ms=0;
u8 LED_FlowDown_ms=0;
#define Lift_Up 999,799,0
#define Lift_Down 999,599,0
#define Door_Open 499,0,299
#define Door_Close 499,0,249
#define All_Stop 499,0,0
u16 LEDn[4]={0X1000,0X2000,0X4000,0X8000}; //上行流水灯
u16 LEDn2[4]={0X8000,0X4000,0X2000,0X1000}; //下行 流水灯
void Delay_Ms(u32 nTime);
void LCD_Init(void);
void GPIO_Int(void);
void KEY_Scan(void);
void Time_Display(uint32_t TimeVar);
void LED_Run(void);
void LED_Flow_Close(void);
int main(void)
{
SysTick_Config(SystemCoreClock/1000);
LCD_Init();
GPIO_Int();
// TIM3_Init(999,799,0) ;//上行
// Delay_Ms(1000);
// TIM3_Init(999,599,0); //下行
// Delay_Ms(1000);
// TIM3_Init(499,0,299); //开门
// Delay_Ms(1000);
// TIM3_Init(499,0,249); //关门
// Delay_Ms(1000);
// TIM3_Init(499,0,0); //停止
// Delay_Ms(1000);
while (1)
{
if(key_flag==1) {KEY_Scan();}
if (TimeDisplay == 1)
{
/* Display current time */
Time_Display(RTC_GetCounter());
TimeDisplay = 0;
}
if(Scan_Up_Flag==1)//电梯向上运行
{
if((Flat2==1)&&(Now_Flat<2))
{
if(Door_State_Flag==1) //关门
{
Door_State_Flag=0;
TIM3_Init(Door_Close); //升降机关门
GPIO_ResetBits(GPIOA, GPIO_Pin_5);
Door_Close_Ms=4000;
}
if(Door_Closefinish_flag==1) // 上行
{
Door_Closefinish_flag=0;
TIM3_Init(Lift_Up); //上行
GPIO_ResetBits(GPIOA, GPIO_Pin_4);
Lift_Motor_Ms=(2-Now_Flat)*6000;
LED_FlowUp_Flag=1;
LED_FlowUp_ms=200;
}
if(Arrive_Floor_flag==1) //开门
{
Arrive_Floor_flag=0;
LED_FlowUp_Flag=0; //关流水灯
LED_Flow_Close();
TIM3_Init(Door_Open);
GPIO_SetBits(GPIOA, GPIO_Pin_5);
Door_Open_ms=4000;
}
if(Stop_flag==1) //开门等待
{
Stop_flag=0;
TIM3_Init(All_Stop);
Door_Wait_ms=2000;
}
if(Door_Wait_flag==1) //停止运行
{
Door_Wait_flag=0;
Flat2=0;
led|=GPIO_Pin_9;
LED_Run();
Now_Flat=2;
Door_State_Flag=1;
LCD_DisplayStringLine(Line4,(unsigned char *)" 2 ");
LCD_FloorTurn_nTime=1;LCD_FloorTurn_ms=500;
}
}
else if((Flat3==1)&&(Now_Flat<3))
{
if(Door_State_Flag==1) //关门
{
Door_State_Flag=0;
TIM3_Init(Door_Close); //升降机关门
GPIO_ResetBits(GPIOA, GPIO_Pin_5);
Door_Close_Ms=4000;
}
if(Door_Closefinish_flag==1) // 上行
{
Door_Closefinish_flag=0;
TIM3_Init(Lift_Up); //上行
GPIO_ResetBits(GPIOA, GPIO_Pin_4);
Lift_Motor_Ms=(3-Now_Flat)*6000;
LED_FlowUp_Flag=1;
LED_FlowUp_ms=200;
}
if(Arrive_Floor_flag==1) //开门
{
Arrive_Floor_flag=0;
LED_FlowUp_Flag=0; //关流水灯
LED_Flow_Close();
TIM3_Init(Door_Open);
GPIO_SetBits(GPIOA, GPIO_Pin_5);
Door_Open_ms=4000;
}
if(Stop_flag==1) //开门等待
{
Stop_flag=0;
TIM3_Init(All_Stop);
Door_Wait_ms=2000;
}
if(Door_Wait_flag==1) //停止运行
{
Door_Wait_flag=0;
Flat3=0;
led|=GPIO_Pin_10;
LED_Run();
Now_Flat=3;
Door_State_Flag=1;
LCD_DisplayStringLine(Line4,(unsigned char *)" 3 ");
LCD_FloorTurn_nTime=1;LCD_FloorTurn_ms=500;
}
}
else if((Flat4==1)&&(Now_Flat<4))
{
if(Door_State_Flag==1) //关门
{
Door_State_Flag=0;
TIM3_Init(Door_Close); //升降机关门
GPIO_ResetBits(GPIOA, GPIO_Pin_5);
Door_Close_Ms=4000;
}
if(Door_Closefinish_flag==1) // 上行
{
Door_Closefinish_flag=0;
TIM3_Init(Lift_Up); //上行
GPIO_ResetBits(GPIOA, GPIO_Pin_4);
Lift_Motor_Ms=(4-Now_Flat)*6000;
LED_FlowUp_Flag=1;
LED_FlowUp_ms=200;
}
if(Arrive_Floor_flag==1) //开门
{
Arrive_Floor_flag=0;
LED_FlowUp_Flag=0; //关流水灯
LED_Flow_Close();
TIM3_Init(Door_Open);
GPIO_SetBits(GPIOA, GPIO_Pin_5);
Door_Open_ms=4000;
}
if(Stop_flag==1) //开门等待
{
Stop_flag=0;
TIM3_Init(All_Stop);
Door_Wait_ms=2000;
}
if(Door_Wait_flag==1) //停止运行
{
Door_Wait_flag=0;
Flat4=0;
led|=GPIO_Pin_11;
LED_Run();
Now_Flat=4;
Door_State_Flag=1;
LCD_DisplayStringLine(Line4,(unsigned char *)" 4 ");
LCD_FloorTurn_nTime=1;LCD_FloorTurn_ms=500;
}
}
else
{
Scan_Up_Flag=0;Scan_Down_Flag=1;
}
}
if(Scan_Down_Flag==1)
{
if((Flat3==1)&&(Now_Flat>3))
{
if(Door_State_Flag==1) //关门
{
Door_State_Flag=0;
TIM3_Init(Door_Close); //升降机关门
GPIO_ResetBits(GPIOA, GPIO_Pin_5);
Door_Close_Ms=4000;
}
if(Door_Closefinish_flag==1) // 下行
{
Door_Closefinish_flag=0;
TIM3_Init(Lift_Down); //下行
GPIO_ResetBits(GPIOA, GPIO_Pin_4);
Lift_Motor_Ms=(Now_Flat-3)*6000;
LED_FlowDown_Flag=1;
LED_FlowDown_ms=200;
}
if(Arrive_Floor_flag==1) //开门
{
Arrive_Floor_flag=0;
LED_FlowDown_Flag=0; //关流水灯
LED_Flow_Close();
TIM3_Init(Door_Open);
GPIO_SetBits(GPIOA, GPIO_Pin_5);
Door_Open_ms=4000;
}
if(Stop_flag==1) //开门等待
{
Stop_flag=0;
TIM3_Init(All_Stop);
Door_Wait_ms=2000;
}
if(Door_Wait_flag==1) //停止运行
{
Door_Wait_flag=0;
Flat3=0;
led|=GPIO_Pin_10;
LED_Run();
Now_Flat=3;
Door_State_Flag=1;
LCD_DisplayStringLine(Line4,(unsigned char *)" 3 ");
LCD_FloorTurn_nTime=1;LCD_FloorTurn_ms=500;
}
}
else if((Flat2==1)&&(Now_Flat>2))
{
if(Door_State_Flag==1) //关门
{
Door_State_Flag=0;
TIM3_Init(Door_Close); //升降机关门
GPIO_ResetBits(GPIOA, GPIO_Pin_5);
Door_Close_Ms=4000;
}
if(Door_Closefinish_flag==1) // 下行
{
Door_Closefinish_flag=0;
TIM3_Init(Lift_Down); //下行
GPIO_ResetBits(GPIOA, GPIO_Pin_4);
Lift_Motor_Ms=(Now_Flat-2)*6000;
LED_FlowDown_Flag=1;
LED_FlowDown_ms=200;
}
if(Arrive_Floor_flag==1) //开门
{
Arrive_Floor_flag=0;
LED_FlowDown_Flag=0; //关流水灯
LED_Flow_Close();
TIM3_Init(Door_Open);
GPIO_SetBits(GPIOA, GPIO_Pin_5);
Door_Open_ms=4000;
}
if(Stop_flag==1) //开门等待
{
Stop_flag=0;
TIM3_Init(All_Stop);
Door_Wait_ms=2000;
}
if(Door_Wait_flag==1) //停止运行
{
Door_Wait_flag=0;
Flat2=0;
led|=GPIO_Pin_9;
LED_Run();
Now_Flat=2;
Door_State_Flag=1;
LCD_DisplayStringLine(Line4,(unsigned char *)" 4 ");
LCD_FloorTurn_nTime=1;LCD_FloorTurn_ms=500;
}
}
else if((Flat1==1)&&(Now_Flat>1))
{
if(Door_State_Flag==1) //关门
{
Door_State_Flag=0;
TIM3_Init(Door_Close); //升降机关门
GPIO_ResetBits(GPIOA, GPIO_Pin_5);
Door_Close_Ms=4000;
}
if(Door_Closefinish_flag==1) // 下行
{
Door_Closefinish_flag=0;
TIM3_Init(Lift_Down); //下行
GPIO_ResetBits(GPIOA, GPIO_Pin_4);
Lift_Motor_Ms=(Now_Flat-1)*6000;
LED_FlowDown_Flag=1;
LED_FlowDown_ms=200;
}
if(Arrive_Floor_flag==1) //开门
{
Arrive_Floor_flag=0;
LED_FlowDown_Flag=0; //关流水灯
LED_Flow_Close();
TIM3_Init(Door_Open);
GPIO_SetBits(GPIOA, GPIO_Pin_5);
Door_Open_ms=4000;
}
if(Stop_flag==1) //开门等待
{
Stop_flag=0;
TIM3_Init(All_Stop);
Door_Wait_ms=2000;
}
if(Door_Wait_flag==1) //停止运行
{
Door_Wait_flag=0;
Flat1=0;
led|=GPIO_Pin_8;
LED_Run();
Now_Flat=1;
Door_State_Flag=1;
LCD_DisplayStringLine(Line4,(unsigned char *)" 1 ");
LCD_FloorTurn_nTime=1;LCD_FloorTurn_ms=500;
}
}
else
{
Scan_Down_Flag=0;key_flag=1;key_ms=10000000;
}
}
}
}
void SysTick_Handler(void)
{
TimingDelay --;
if(--key_ms==0)
{
key_flag=0;
Scan_Up_Flag=1 ;
}
if(--Door_Close_Ms==0)
{
Door_Closefinish_flag=1;
}
if(--Lift_Motor_Ms==0)
{
Arrive_Floor_flag=1;
}
if(--Door_Open_ms==0)
{
Stop_flag=1;
}
if(--Door_Wait_ms==0)
{
Door_Wait_flag=1;
}
if((LED_FlowUp_Flag==1)&&(--LED_FlowUp_ms==0)) //上行 流水灯
{
LED_FlowUp_ms=200;
LED_Flow_Close();
led&=~LEDn[i];LED_Run();
i++;
if(i==4)
i=0;
}
if((LED_FlowDown_Flag==1)&&(--LED_FlowDown_ms==0)) //下行 流水灯
{
LED_FlowDown_ms=200;
LED_Flow_Close();
led&=~LEDn2[i];LED_Run();
i++;
if(i==4)
i=0;
}
if((LCD_FloorTurn_nTime>0)&&(--LCD_FloorTurn_ms==0)) //闪烁
{
LCD_FloorTurn_ms=500;
if(LCD_FloorTurn_nTime==1)
{
LCD_DisplayStringLine(Line4,(unsigned char *)" ");
LCD_FloorTurn_nTime++;
}
else if(LCD_FloorTurn_nTime==2)
{
sprintf((char*)string," %d ",Now_Flat );
LCD_DisplayStringLine(Line4,string);
LCD_FloorTurn_nTime++;
}
else if(LCD_FloorTurn_nTime==3)
{
LCD_DisplayStringLine(Line4,(unsigned char *)" ");
LCD_FloorTurn_nTime++;
}
else if(LCD_FloorTurn_nTime==4)
{
sprintf((char*)string," %d ",Now_Flat );
LCD_DisplayStringLine(Line4,string);
LCD_FloorTurn_nTime=0;
}
}
}
void KEY_Scan(void)
{
if(RB1==0)
{
Delay_Ms(10);
if(RB1==0&&Now_Flat!=1)
{
Flat1=1;
key_ms=1000;
led&=~GPIO_Pin_8;
LED_Run();
}
while(!RB1);
}
else if(RB2==0)
{
Delay_Ms(10);
if(RB2==0&&Now_Flat!=2)
{
Flat2=1;
key_ms=1000;
led&=~GPIO_Pin_9;
LED_Run();
}
while(!RB2);
}
else if(RB3==0)
{
Delay_Ms(10);
if(RB3==0&&Now_Flat!=3)
{
Flat3=1;
key_ms=1000;
led&=~GPIO_Pin_10;
LED_Run();
}
while(!RB3);
}
else if(RB4==0)
{
Delay_Ms(10);
if(RB4==0&&Now_Flat!=4)
{
Flat4=1;
key_ms=1000;
led&=~GPIO_Pin_11;
LED_Run();
}
while(!RB4);
}
}
void LED_Run(void)
{
GPIO_Write(GPIOC,led);
GPIO_SetBits(GPIOD,GPIO_Pin_2);
GPIO_ResetBits(GPIOD,GPIO_Pin_2);
}
void LED_Flow_Close(void)
{
led|=GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
LED_Run();
}
void Time_Display(uint32_t TimeVar)
{
uint32_t THH = 0, TMM = 0, TSS = 0;
/* Reset RTC Counter when Time is 23:59:59 */
if (RTC_GetCounter() == 0x0001517F)
{
RTC_SetCounter(0x0);
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask();
}
/* Compute hours */
THH = TimeVar / 3600;
/* Compute minutes */
TMM = (TimeVar % 3600) / 60;
/* Compute seconds */
TSS = (TimeVar % 3600) % 60;
sprintf((char*)string," %0.2d: %0.2d: %0.2d ", THH, TMM, TSS);
LCD_DisplayStringLine(Line5,string);
}
void Delay_Ms(u32 nTime)
{
TimingDelay = nTime;
while(TimingDelay != 0);
}
⑤、代码分析
因为频繁使用滴答定时器,故将其中断服务函数写在主函数,方便定义变量;其次是频率的计算
频率:
//Fpwm = 72M / ((arr+1)*(psc+1))(单位:Hz)
占空比:
//duty circle = TIM3->CCR1 / arr(单位:%)
再有是流水灯,采用GPIO_Write函数,并用数组保存;升降机运行的顺序为是否上行,若上行,升降机关门——上行——开门——停止运行——开门等待;这样的顺序,其中led楼层指示灯、流水灯、到达楼层闪烁等分别写在相应的步骤中这里不再赘述,具体看程序注解。