|
总体方案设计 总述系统由哪些模块组成,然后画出系统结构框图(宋体 小四号,18磅行间距) 本设计主要由单片机控制模块、按键输入模块、电机驱动模块、数码管显示模块和LED指示模块组成。 5 硬件电路设计 5.1 51单片机最小系统设计 (宋体 小四号,18磅行间距) 51单片机最小系统电路由以下部分组成: 单片机芯片:这是51单片机最小系统电路的核心部分,通常选用AT89C51、AT89C52等常见的51系列单片机。 晶振电路:这个电路用来为单片机提供工作时钟,通常由一个晶振和两个电容组成。晶振的频率通常为11.0592MHz或12MHz,这两个频率是51单片机的标准工作频率。 复位电路:复位电路用来在上电时或其他情况下对单片机进行复位,确保单片机能够正常启动和工作。 复位电路通常由一个电阻、电容和一个复位按钮组成。 电源电路:电源电路为整个51单片机最小系统电路提供电源,通常由一个稳压电源组成。51单片机的工作电压通常为5V,因此电源电路需要将外部电压转换为5V。 本设计中单片机负责读取按键输入,控制电机、LED和数码管执行命令。 5.2 按键输入模块电路设计 (宋体 小四号,18磅行间距) 按键电路模块由4×8的矩阵按键组成,分别对应八层楼的电梯门开关、电梯外向下按键、电梯向上按键、以及电梯内数字键盘按键。通过12个IO口与单片机连接,用户按下对应按键时,单片机接收到信号执行对应命令。 5.3 电机驱动模块电路设计 电机驱动模块负责控制直流电机正反转,从而拖动电梯上下运动。采用了光电耦合器和电磁开关的设计。当单片机IO输出低电平时三极管导通,光电耦合器导通,电磁开关得电,直流电机运行。 5.4 数码管显示模块电路设计 数码管显示模块由两个74HC595和两个数码管组成。74HC595具有串行输入,并行输出的功能。74HC595负责将单片机IO输出的串行数据,并行输出到数码管,通过控制数码管内部LED灯的亮灭达到显示不同数字的效果。 5.5 LED指示模块电路设计 LED指示模块电路主要由LED灯,74HC595组成。LED灯位于按键下部,负责指示按键作用效果。当键盘按下之后单片机得到按下按键的数据,然后输出到74HC595,进行串并转换后对应LED亮起。 6 软件设计 6.1 软件总体流程 (宋体 小四号,18磅行间距) 软件部分主要负责矩阵按键的扫描、控制逻辑的实现、电机正反转控制、晶体管和LED的显示控制。 启动时,对系统进行初始化,电梯楼层显示为1,LED指示灯不亮。初始化完成之后等待用户按键,按键完成之后进入楼层呼叫处理函数,根据当前运行状态控制电梯的上下移动命令,由电梯动作函数,控制电梯具体的上下移动,同时数码管显示当前电梯所在楼层。 6.2主函数 (宋体 小四号,18磅行间距) 主函数负责完成系统初始化以及循环执行任务。
1. void main(void)
2. {
3. SYSYEM_INIT();
4. EXTI0_Init();
5. EXTI1_Init();
6. TIMER0_Init();
7. while(1)
8. {
9. KeyPort_Y=0x00;
10. FloorCallCheck();
11. Elevator();
12. }
13.}
6.3 楼层呼叫处理函数
当按键按下之后,根据当前电梯所在楼层和按下楼层进行判断。若当前电梯正在上升或下降运行(此时八段码显示楼层变化,LED 指示希望抵达的楼层),若键入新的希望停的楼层数字(相应的 LED 亮),则对同方向(上升或下降)未到的楼层能停,对其它情况则先停原希望停的楼层,然后按运行键后继续运行。
1. void FloorCallCheck(void)
2. {
3. if(DelNullCheck()==FALSE)
4. {
5. ElevState.FreeFlag=FALSE;
6. ElevState.ElevRunning=TRUE;
7. }
8. else ElevState.FreeFlag=TRUE;
9. TurnHead_Check();
10. if((ElevState.FreeFlag==FALSE)&&(DOOR==CLOSE))
11. {
12. if(ElevState.Direction==UP)
13. {
14. if((FloorCall_UP(UP)==TRUE)||(FloorCall_DOWN(UP)==TRUE))
15. {
16.
17. if(ElevState.FloorTimerCount>FloorStayTime)
18. {
19. ElevState.FloorTimerCount=0;
20. ElevState.CurrentFloor++;
21. }
22.
23. }
24. else ElevState.Direction=DOWN;
25. }
26. else
27. if(ElevState.Direction==DOWN)
28. {
29. if((FloorCall_DOWN(DOWN)==TRUE)||(FloorCall_UP(DOWN)==TRUE))
30. {
31.
32. if(ElevState.FloorTimerCount>FloorStayTime)
33. {
34. ElevState.FloorTimerCount=0;
35. ElevState.CurrentFloor--;
36. }
37. }
38. else ElevState.Direction=UP;
39. }
40. }
41. else
42. {
43. ElevWorkState(STOP);
44. ElevState.ElevRunning=FALSE;
45. }
46.}
6.4 调头检测函数
将电梯运行状态取反
1. void TurnHead_Check(void)
2. {
3. if(ElevState.CurrentFloor==1)
4. {
5. ElevState.Direction=UP;
6. }
7. else if(ElevState.CurrentFloor==MaxFloor)
8. {
9. ElevState.Direction=DOWN;
10. }
11.}
6.5 电梯运行状态配置函数
配置电梯运行的三种状态上升、下降和停止。
1. void ElevWorkState(u8 state)
2. {
3. if(state==UP)
4. {
5. Elev_UP;
6. ElevState.ElevRunning=TRUE;
7. }
8. else
9. if(state==DOWN)
10. {
11. Elev_DOWN;
12. ElevState.ElevRunning=TRUE;
13. }
14. else
15. if(state==STOP)
16. {
17. Elev_STOP;
18. ElevState.ElevRunning=FALSE;
19. }
20. SEG_Display(ElevState.CurrentFloor);
21.}
6.6 电梯运行函数
控制电梯运行到对应的楼层,楼层数为8层,键盘数字键 1~8 用来键入希望停的楼层,8个LED 显示希望停的楼层,2位八段码指示电梯当前所在楼层,按钮用来启、停电梯。电梯正常运行时以每2秒1层的速度上升或下降。
1. void Elevator(void)
2. {
3. if((DOOR==OPEN)||(ElevState.FreeFlag==TRUE)) ElevWorkState(STOP);
4. else ElevWorkState(ElevState.Direction);
5. TurnHead_Check();
6. if(ElevState.Direction==UP)
7. {
8. if(ElevState.CurrentFloor<=MaxFloor)
9. {
10. if(((ElevState.FloorCallTable[ElevState.CurrentFloor]&UP_IN)==UP_IN)||((ElevState.FloorCallTable[ElevState.CurrentFloor]&UP_OUT)==UP_OUT))
11. {
12. LED_OFF(LED_IN_Port,ElevState.CurrentFloor);
13. LED_OFF(LED_OUT_UP_Port,ElevState.CurrentFloor);
14. ElevState.FloorCallTable[ElevState.CurrentFloor]&=~UP_IN;
15. ElevState.FloorCallTable[ElevState.CurrentFloor]&=~UP_OUT;
16. ElevState.FreeFlag=TRUE;
17. ElevWorkState(STOP);
18. WaitDoorOpen(DoorStayTime);
19. delay_s(2*DoorStayTime);
20. WaitDoorClose(DoorStayTime);
21. ElevWorkState(ElevState.Direction);
22. ElevState.FreeFlag=FALSE;
23. ElevState.FloorTimerCount=0;
24. }
25. }
26. }
27. else
28. if(ElevState.Direction==DOWN)
29. {
30. if(ElevState.CurrentFloor>=1)
31. {
32. if(((ElevState.FloorCallTable[ElevState.CurrentFloor]&DOWN_IN)==DOWN_IN)||((ElevState.FloorCallTable[ElevState.CurrentFloor]&DOWN_OUT)==DOWN_OUT))
33. {
34. LED_OFF(LED_IN_Port,ElevState.CurrentFloor);
35. LED_OFF(LED_OUT_DOWN_Port,ElevState.CurrentFloor);
36. ElevState.FloorCallTable[ElevState.CurrentFloor]&=~DOWN_IN;
37. ElevState.FloorCallTable[ElevState.CurrentFloor]&=~DOWN_OUT;
38. ElevState.FreeFlag=TRUE;
39. ElevWorkState(STOP);
40. WaitDoorOpen(DoorStayTime);
41. delay_s(2*DoorStayTime);
42. WaitDoorClose(DoorStayTime);
43. ElevWorkState(ElevState.Direction);
44. ElevState.FreeFlag=FALSE;
45. ElevState.FloorTimerCount=0;
46. }
47. }
48. }
49.
50.}
6.7 按键扫描函数
通过实时扫描按键状态,获取用户控制命令。
1. u8 KeyScan(void)
2. {
3. u8 keynum;
4.
5. KeyPort_Y=0x00;
6. KeyPort_X=0xFF;
7. _nop_(); _nop_(); _nop_(); _nop_();
8. if(KeyPort_X!=0xFF)
9. {
10. delay_ms(10);
11. if(KeyPort_X!=0xFF)
12. {
13. switch(KeyPort_X)
14. {
15. case 0x7F: keynum=1; break;
16. case 0xBF: keynum=9; break;
17. case 0xDF: keynum=17; break;
18. case 0xEF: keynum=25; break;
19. case 0xF7: keynum=33; break;
20. case 0xFB: keynum=41; break;
21. case 0xFD: keynum=49; break;
22. case 0xFE: keynum=57; break;
23. }
24. KeyPort_Y=0xFF;
25. KeyPort_X=0x00;
26. _nop_(); _nop_(); _nop_(); _nop_();
27. if(KeyPort_Y!=0xFF)
28. {
29. switch(KeyPort_Y)
30. {
31. case 0xFE: keynum=keynum+0; break;
32. case 0xFD: keynum=keynum+1; break;
33. case 0xFB: keynum=keynum+2; break;
34. case 0xF7: keynum=keynum+3; break;
35. case 0xEF: keynum=keynum+4; break;
36. case 0xDF: keynum=keynum+5; break;
37. case 0xBF: keynum=keynum+6; break;
38. case 0x7F: keynum=keynum+7; break;
39. }
40. }
41. KeyPort_Y=0x00;
42. }
43. }
44. else keynum=0;
45. return keynum;
46.}
6.8 数码管显示函数
通过IO给74HC595发送对应数据,数码管显示对应内容。
1. void SEG_Display(u8 segnum)
2. {
3. HC595_BUFF[0]=SEG_NUM[segnum/10];
4. HC595_BUFF[1]=SEG_NUM[segnum%10];
5. HC595_Send(HC595_BUFF);
6. }
6.9 LED显示函数
通过IO给74HC595发送对应数据,对应LED灯亮灭。
1. void LED_ON(u8 addr,u8 lednum)
2. {
3. switch(addr)
4. {
5. case LED_IN_Port: if(lednum<9) HC595_BUFF[2]|=LED_NUM[lednum];
6. else HC595_BUFF[5]|=LED_NUM[lednum-8]; break;
7. case LED_OUT_DOWN_Port: if(lednum<9) HC595_BUFF[3]|=LED_NUM[lednum];
8. else HC595_BUFF[6]|=LED_NUM[lednum-8]; break;
9. case LED_OUT_UP_Port: if(lednum<9) HC595_BUFF[4]|=LED_NUM[lednum];
10. else HC595_BUFF[7]|=LED_NUM[lednum-8]; break;
11. }
12. HC595_Send(HC595_BUFF);
13.}
14.
15.void LED_OFF(u8 addr,u8 lednum)
16.{
17. switch(addr)
18. {
19. case LED_IN_Port: if(lednum<9) HC595_BUFF[2]&=~LED_NUM[lednum];
20. else HC595_BUFF[5]&=~LED_NUM[lednum-8]; break;
21. case LED_OUT_DOWN_Port: if(lednum<9) HC595_BUFF[3]&=~LED_NUM[lednum];
22. else HC595_BUFF[6]&=~LED_NUM[lednum-8]; break;
23. case LED_OUT_UP_Port: if(lednum<9) HC595_BUFF[4]&=~LED_NUM[lednum];
24. else HC595_BUFF[7]&=~LED_NUM[lednum-8]; break;
25. }
26. HC595_Send(HC595_BUFF);
27.}
资料下载:http://www.51hei.com/bbs/dpj-239689-1.html |