找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1629|回复: 1
打印 上一主题 下一主题
收起左侧

最近做的一个东西, 涉及到单片机定时器使用, UART, RS485, STC单片机片内EEPROM操作.

[复制链接]
跳转到指定楼层
楼主
ID:365802 发表于 2019-5-15 09:01 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
如题, 提供给大家参考. 也欢迎大神指正.

工程文档在附件中.

单片机源程序如下:
  1. #include "reg51.h"
  2. #include "main.h"
  3. #include "EEPROM.h"

  4. #define uchr unsigned char
  5. #define uint unsigned int

  6. //#define FOSC 11059200L                      //System frequency
  7. #define FOSC 12000000L                      //System frequency
  8. //#define BAUD 9600                           //UART baudrate
  9. #define T1MS (65536-FOSC/12/1000)   //1ms timer calculation method in 12T mode

  10. #define ON  1                                //定義ON
  11. #define OFF 0                                //定義OFF
  12. #define STARTBYTE 0x24                //開始字節
  13. #define STOPBYTE  0x2a                //結束字節

  14. #define UART_P1() (AUXR1 |= 0x80)        //串口切換到P1口
  15. #define UART_P3() (AUXR1 &= 0x7f)        //串口切換到P3口

  16. uchr Settings[2];                        //從EEPROM讀取的設定
  17. uchr addr;                                        //系統地址
  18. bit  PowerONWhenSTARTUP;        //系統上電ESD是否開啟(保留)
  19. bit         flagRec_OK;                        //標誌位, 接收完成
  20. bit  flagBusy;                                //標誌位, 發送忙
  21. uchr recBuff[5];                        //接收緩存


  22. bit  flagWriteEN;                        //標誌位, 寫地址使能
  23. uchr ESDState;                                //ESD狀態 1-> PASS, 2 -> FAIL, 3 -> POWEROFF, 4 -> IDLE
  24. uchr PowerState;                        //ESD電源狀狀態 0-> 關閉, 1-> 開啟, 2->空閒.

  25. sfr  AUXR                = 0x8e;                //輔助寄存器
  26. sfr  AUXR1                = 0xa2;                //串口選擇寄存器
  27. sfr  BRT                = 0x9c;

  28. sbit pin485EN         = P1^4;                //485寫使能
  29. sbit pinESDState= P1^3;                //ESD偵測
  30. sbit pinLampG        = P1^2;                //綠燈
  31. sbit pinLampR        = P1^1;                //紅燈
  32. sbit pinESDPower= P1^0;                //ESD電源
  33. sbit pinWriteEN        = P3^5;                //寫地址使能
  34. sbit pinSensor  = P3^7;                //感應器



  35. extern void delayms(uint ms);        //毫秒延時函數
  36. extern void SysInit(void);                //系統初始化
  37. extern void sendData(uchr dat);        //發送1Byte
  38. extern void UartSend(uchr cmd,dat);        //發送一幀
  39. extern void UartDriver(void);        //串口數據處理
  40. extern void LampControl(uchr t);        //燈控制
  41. extern void UartChangePort(void);        //串口切換
  42. extern void HumanDetection(void);        //人員檢測



  43. /**************主函數******************/
  44. void main(void)
  45. {
  46.         SysInit();
  47.         
  48.         for(;;)
  49.         {

  50.                 UartChangePort();
  51.                 HumanDetection();
  52.                 UartDriver();
  53.                 if(PowerState == 1) LampControl(ESDState);
  54.         }
  55. }

  56. //#############################
  57. //毫秒延時
  58. //#############################
  59. void delayms(uint ms)
  60. {
  61.         unsigned char i, j;

  62.          do{
  63.                 i = 11;
  64.                 j = 190;
  65.                 do
  66.                 {
  67.                         while (--j);
  68.                 } while (--i);
  69.         } while (--ms);        
  70. }

  71. //#############################
  72. //發送1byte
  73. //#############################
  74. void sendData(uchr dat)
  75. {
  76.         while(flagBusy);                //檢測是否還在發送狀態
  77.         flagBusy = 1;
  78.         SBUF = dat;
  79. }        

  80. //#############################
  81. //發送1幀
  82. //485接收發送狀態轉換時應提前, 以適應電路的反應時間. 特別是發送完成. 延時不夠易造成停止位發送失敗.
  83. //#############################
  84. void UartSend(uchr cmd,dat)
  85. {
  86.         pin485EN = 0;                        //485發送使能
  87.         delayms(1);                                //延時
  88.         sendData(STARTBYTE);        //發送開始位
  89.         sendData(addr);                        //發送地址
  90.         sendData(cmd);                        //發送指令
  91.         sendData(dat);                        //發送數據
  92.         sendData(STOPBYTE);                //發送結束位
  93.         delayms(1);                                //延時,此時發送停止位
  94.         pin485EN = 1;                        //485發送禁止
  95. }
  96. //#############################
  97. //人員檢測, 僅在電源開啟時起作用
  98. //#############################
  99. void HumanDetection(void)
  100. {
  101.         static uint DetecCount = 0;

  102.         
  103.         if(DetecCount <= 3000)                //設置檢測間隔時間, 防止人員動作造成誤判
  104.         {
  105.                 delayms(1);
  106.                 DetecCount++;
  107.         } else        {
  108.                 DetecCount = 0;
  109.                 if(PowerState == 1)                        //確認為開啟狀態
  110.                 {
  111.                         if(pinSensor == 1)                //確認人員離開
  112.                         {
  113.                                 delayms(200);
  114.                                 if(pinSensor == 1)
  115.                                 {
  116.                                         PowerState        = 2;        //進入空閒狀態
  117.                                         pinLampG        = OFF;                //綠燈
  118.                                         pinLampR        = OFF;                //紅燈
  119.                                         pinESDPower        = OFF;                //ESD電源
  120.                                 }
  121.                         }
  122.                 } else if(PowerState == 2)        //空閒狀態
  123.                 {
  124.                         if(pinSensor == 0)        //確認人員就位
  125.                         {
  126.                                 delayms(200);
  127.                                 if(pinSensor == 0)
  128.                                 {
  129.                                         PowerState        = 1;        //進入開啟狀態
  130.                                         pinESDPower        = ON;                //ESD電源
  131.                                 }
  132.                         }
  133.                 }
  134.         }
  135. }

  136. //#############################
  137. //燈控制
  138. // 1-> 綠燈 2-> 紅燈 其他燈滅
  139. //#############################
  140. void LampControl(uchr t)
  141. {
  142.         static uchr lampState = 4;        //上一次的燈狀態, 燈狀態只有0,1,2. 默認4防止上電后狀態不變燈顯示錯誤.
  143.         
  144.         if(lampState != t)
  145.         {
  146.                 lampState = t;
  147.                 pinLampG = OFF;
  148.                 pinLampR = OFF;
  149.                 switch(t)
  150.                 {
  151.                         case 1:
  152.                                 pinLampG = ON;
  153.                                 break;
  154.                         case 2:
  155.                                 pinLampR = ON;
  156.                                 break;
  157.                         default:
  158.                                 break;
  159.                 }
  160.         }
  161. }
  162. //#############################
  163. //串口切換
  164. //單片機默認串口在P3, 所以初始化的時候不用設置
  165. //#############################
  166. void UartChangePort(void)
  167. {
  168.         static uchr UartPort;
  169.         if(UartPort != pinWriteEN)                //用個標誌位判斷防止不斷寫寄存器
  170.         {
  171.                 UartPort = pinWriteEN;
  172.                 if(pinWriteEN == 0)                        //下載端口最後一pin短接到地時, 串口從P1切換到P3. 可使用TTL進行通信調試.
  173.                 {
  174.                         UART_P3();
  175.                 } else {
  176.                         UART_P1();
  177.                 }
  178.         }
  179. }
  180. //#############################
  181. //串口數據處理
  182. //檢查接收完成狀態位flagRec_OK為1, 進函數進行處理.
  183. //#############################
  184. void UartDriver(void)
  185. {
  186.         uchr returnDat;                        //返回的數據
  187.         uchr returnCmd;                        //返回的指令
  188.         uchr recCmd;                        //收到的指令
  189.         uchr recDat;                        //收到的數據
  190.         if(flagRec_OK)                        //判斷接收標誌位
  191.         {
  192.                 flagRec_OK = 0;
  193.                 if((recBuff[1] == addr) || recBuff[1] == 0xff)                //判斷數據幀中的地址位是否與本機一致, 或者數據幀的地址位廣播地址0xff
  194.                 {
  195.                         recCmd          = recBuff[2];
  196.                         returnCmd = recCmd;
  197.                         recDat          = recBuff[3];
  198.                         returnDat = 1;
  199.                         
  200.                         switch(recCmd)
  201.                         {
  202.                                 case 0x11:                //感應器測試
  203.                                         returnDat         = pinSensor;
  204.                                         break;
  205.                                 case 0x22:                //ESD狀態
  206.                                         returnDat         = ESDState;
  207.                                         break;
  208.                                 
  209.                                 case 0x30:                //關閉ESD電源
  210.                                         PowerState         = 0;
  211.                                         pinESDPower        = OFF;
  212.                                         pinLampG        = OFF;
  213.                                         pinLampR        = OFF;
  214.                                         break;
  215.                                 case 0x31:                //開啟ESD電源
  216.                                         PowerState = 1;
  217.                                         pinESDPower = ON;
  218.                                         break;
  219.                                 
  220.                                 case 0x41:                //開綠燈, 只能在ESD關閉狀態下
  221.                                         if(PowerState == 0)
  222.                                         {
  223.                                                 pinLampG        = ON;
  224.                                                 pinLampR        = OFF;
  225.                                         } else {
  226.                                                 returnDat = 0;
  227.                                         }
  228.                                         break;
  229.                                 case 0x42:                //開紅燈, 只能在ESD關閉狀態下
  230.                                         if(PowerState == 0)
  231.                                         {
  232.                                                 pinLampG        = OFF;
  233.                                                 pinLampR        = ON;
  234.                                         } else {
  235.                                                 returnDat = 0;
  236.                                         }
  237.                                         break;
  238.                                 case 0x50:                //使能地址寫
  239.                                         flagWriteEN = 1;
  240.                                         break;
  241.                                 
  242.                                 case 0x51:                //寫地址
  243.                                         //if((flagWriteEN == 1) && (pinWriteEN == 0))        //檢查地址寫是否使能
  244.                                         if(flagWriteEN == 1)        //檢查地址寫是否使能
  245.                                         {
  246.                                                 Settings[0] = recDat;
  247.                                                 addr                = recDat;
  248.                                                 ISP_IAP_EraseData(0);
  249.                                                 ISP_IAP_WriteData(0,Settings,2);
  250.                                         } else {
  251.                                                 returnDat = 0;
  252.                                         }
  253.                                         break;
  254.                                 default:                //無法匹配的指令返回0xff
  255.                                         returnDat = 0xff;
  256.                                         break;
  257.                         }
  258.                         UartSend(returnCmd, returnDat);                //發送返回數據
  259.                 }
  260.         }
  261. }
  262. //#############################
  263. //系統初始化
  264. //#############################
  265. void SysInit(void)
  266. {
  267. ///*******寄存器初始化**********/
  268.         TL0 = T1MS;                        //計時器0 1毫秒 初值
  269.         TH0 = T1MS >> 8;
  270.         TR0        = 1;                        //開啟計時器0
  271.         ET0 = 1;                        //開啟計時器0中斷


  272.         PCON &= 0x7F;                //波特率不倍速
  273.         SCON = 0x50;                //8位數據,可變波特率
  274.         BRT = 0xD9;                        //獨立波特率初裝值
  275.         AUXR |= 0x04;                //獨立波特率1T
  276.         AUXR |= 0x01;                //串口1波特率發生器選擇為獨立波特率發生器
  277.         AUXR |= 0x10;                //啟動獨立波特率發生器
  278.         
  279.         UART_P1();                        //將串口切換到P1口
  280.         
  281.         ES                = 1;                //開串口中斷
  282.         EA                = 1;                //開總中斷
  283.         
  284. /*******設定初始化**************/
  285.         ISP_IAP_ReadData(0x00,Settings,2);                        //從EEPROM中讀取3個Byte資料
  286.         addr = Settings[0];                                                        //地址
  287.         PowerONWhenSTARTUP = (bit)(Settings[1]);        //開機狀態, 先做在這裡, 但不做處理
  288.         
  289. /*******端口初始化*************/        
  290.         pin485EN         = 1;        //禁止485發送, 備註: 485默認通過電阻弱下拉, 接收狀態, 使能端低電平使光耦導通, 485使能端轉為高電平發送狀態.
  291.         pinESDState = 1;
  292.         pinWriteEN        = 1;
  293.         pinESDPower = ON;
  294.         pinLampG        = OFF;
  295.         pinLampR        = OFF;
  296.         
  297. /*******變量初始化**************/
  298.         PowerState  = 1;        //默認電源開啟
  299.         flagWriteEN = 0;        //禁止寫地址

  300. }

  301. //#############################
  302. //串口中斷, 接收上位機數據
  303. //數據幀格式
  304. //  24   | 地址   | 指令   | 數據   | 2A
  305. //開始位 | 地址位 | 指令位 | 數據位 | 結束位
  306. //#############################
  307. void uart_isr() interrupt 4
  308. {
  309.         static bit recStart;        //接收開始
  310.         static bit recStop;                //接收結束
  311.         static uchr recIdx;                //接收序號
  312.         uchr   recTmp;                        //接收緩存
  313.         
  314.         if(TI)                //發送
  315.         {
  316.                 TI = 0;
  317.                 flagBusy = 0;
  318.         } else {        //接收
  319.                 RI = 0;
  320.                 recTmp = SBUF;
  321.                
  322.                 if((recTmp == STARTBYTE) && (recStart == 0)) //判斷接收開始
  323.                 {
  324.                         recStart         = 1;
  325.                         recStop          = 0;
  326.                         recIdx                 = 0;
  327.                         flagRec_OK  = 0;
  328.                 }
  329.                
  330.                 if((recStart == 1) && (recStop == 0))                //接收數據
  331.                 {
  332.                         recBuff[recIdx++] = recTmp;
  333.                         
  334.                         if((recTmp == STOPBYTE) || (recIdx >= 5))        //判斷接收結束
  335.                         {
  336.                                 recStop                = 1;
  337.                                 recStart        = 0;
  338.                                 flagRec_OK        = 1;
  339.                         }
  340.                 }
  341.         }
  342. }
  343. //#############################
  344. //計時器0中斷函數, 用於獲取ESD狀態
  345. //數據來源是一個指示異常的閃爍紅燈LED電壓, 燈亮時為0, 燈滅為1.
  346. //#############################
  347. void tm0_isr() interrupt 1 using 1
  348. {
  349.         static uint count;
  350.         static uchr lampStates[8];                //採集的狀態, 共8個
  351.         static uchr lampStateIdx;                //燈狀態數據Idx
  352.         uchr i;

  353.         TL0 = T1MS;                     //reload timer0 low byte
  354.     TH0 = T1MS >> 8;                //reload timer0 high byte
  355.     if (count++ == 250)             //每250毫秒採集一次紅燈的狀態, 保存在狀態數組中, 從數組判斷當前系統的狀態
  356.     {
  357.         count = 0;                       //reset counter
  358.                
  359.                 if(PowerState == 0)                        //關閉狀態, 採集狀態 = 3
  360.                 {
  361.                         lampStates[lampStateIdx++] = 3;
  362.                 } else if(PowerState == 1)        //開啟狀態, 採集狀態 = 紅燈關聯
  363.                 {        
  364.                         lampStates[lampStateIdx++] = pinESDState ? 1 : 2;
  365.                 } else if(PowerState == 2){        //空閒狀態, 採集狀態 = 4
  366.                         lampStates[lampStateIdx++] = 4;
  367.                 }


  368.                 if(lampStateIdx >=8)                //分析採集數組
  369.                 {
  370.                         lampStateIdx = 0;
  371.                         for(i=0; i<8; i++)
  372.                         {
  373.                                 if(lampStates[i] == 4)                        //如有採集結果中有4, 狀態為空閒
  374.                                         {
  375.                                         ESDState = 4;
  376.                                         break;        
  377.                                 } else if(lampStates[i] == 3)        //如有採集結果中有3, 狀態為關閉
  378.                                 {
  379.                                         ESDState = 3;
  380.                                         break;
  381.                                 } else if(lampStates[i] == 2)        //如果採集結果中有2, 狀態為異常
  382.                                 {
  383.                                         ESDState = 2;
  384.                                         break;
  385.                                 } else {                                                //否則, 狀態為正常.
  386.                                         ESDState = 1;
  387.                                 }
  388.                         }
  389.                 }
  390.     }
  391. }
复制代码
全部资料51hei下载地址:
ESDMonitor.zip (57.42 KB, 下载次数: 22)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:43342 发表于 2019-6-4 20:35 | 只看该作者
谢谢楼主!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表