![]() |
發布時間: 2022-7-16 23:19
正文摘要:最近做了一個小項目,用兩塊單片機共同控制一塊lcd1602。思路是這樣的,a單片機的p0.0-0.4控制lcd1602 dat的低四位,b單片機的p0.0-0.4控制lcd1602 dat的高四位。1602的rs rw e口都在a單片機的 p27 26 25,數據和指 ... |
美琴的備胎 發表于 2022-7-17 15:27 雖說這樣驅動1602有點自找麻煩,但還是能成功。仿真沒有問題,未經實物驗證。 ![]() ![]() |
美琴的備胎 發表于 2022-7-17 20:21 你的目的是想知道"關于兩塊51單片機共同控制lcd1602" 很顯然,這個問題已經不重要了,整個問題的重心已經變成了誰失去了對新鮮事物的接受能力,誰比誰年輕 再討論下去可能就會變成我的技術比你好,或者是你的技術比我好之類的了 你本來是想要一條魚的,我覺得單給你一條魚好像不能解決問題,我就笑咪咪問你"你為什么要魚呢?要不要我教你怎么打魚" 我的笑到了你那里,就變成嘲笑,然后,你就開始跟我爭論誰比誰思想更先進 至于你原本想要的魚,早就不重要了 如果是我問題這個問題,肯定不是你這樣的 我會把我的想法告訴大家,我要做什么東西,比如是接收某個串口的數據,然后控制另外一個硬件 如果別人嘲笑我想法很蠢,那我就會問"那怎么做好點呢?" 如果不是商業機密,我還會把硬件電路上傳 而不是像你這樣,把時間浪費在跟不認識的人去爭論一個跟問題本身沒有半點關系,而且不會結果的答案這就是你跟我的不同 我就是無聊,打字就是打發時間,那么,我的目的已經達到了 |
美琴的備胎 發表于 2022-7-17 20:21 用最簡單的話來講: 可以, 這里更正一下: 8樓的提到的第3點已經指出了一個方向,雖然不是唯一方向。可惜你看不明白。 不可以,因為你的知識儲備,和對單片機的原理,以及LCD的工作原理的理解不夠,不足以支撐你完成這樣構想。 撇開實用性不講,如果,你純粹為了達成這樣的構想而要繼續做下去的話,建議你了解一下"同步時鐘"的概念,這是你這個項目繼續下去的必要條件。 |
美琴的備胎 發表于 2022-7-17 20:21 用最簡單的話來講: 可以,10樓的提到的第3點已經指出了一個方向,雖然不是唯一方向。可惜你看不明白。 不可以,因為你的知識儲備,和對單片機的原理,以及LCD的工作原理的理解不夠,不足以支撐你完成這樣構想。 撇開實用性不講,如果,你純粹為了達成這樣的構想而要繼續做下去的話,建議你了解一下"同步時鐘"的概念,這是你這個項目繼續下去的必要條件。 |
lkc8210 發表于 2022-7-17 18:59 因為我要傳的東西很多,比如L代表是傳輸lcd1602信號,類似的還有P是代表傳輸的io口數據,U代表傳輸的串口數據,前四位不用解釋了,是io口,其他位計劃要帶數據的,就是顯示的內容 |
Y_G_G 發表于 2022-7-17 15:58 真的搞不懂,明明跟簡單的問題,可以,有什么錯誤指出來,或者不行。你用了一多半的篇幅提那么多沒用的東西干嘛,引經據典看似字數很多,實則長篇大論,整個文章的重點只有一小段話,你是抓不到重點嗎? |
188610329 發表于 2022-7-17 16:42 標題就是我的欲望,誘惑就是這樣做出來我能開心。我只是自己玩,有必要把io內存這些資源算的這么清楚嗎?難道兩塊單片機控制lcd1602不是探索?不是創新?你可以覺得很滑稽,很搞笑,很浪費,但我就是覺得很有趣,你認為的'提高和進步'明顯已經功利化了,你認為降低成本才是提高和創新,抱歉,我還年輕,我還可以揮霍 |
hhdsdy 發表于 2022-7-17 17:19 標題沒有,正文有沒有,連看都不看是吧?八位dat口不是并行是什么?難道我問題多不是因為我做的東西多嗎?你看看我提問的有一個是直接要程序的嗎?有的人一年做不了幾個項目,做的還都是csdn一搜就能搜到的,你好好看看我是提問題提的多,還是提供程序提供的多?我800多積分都是提問題提出的嗎?再說其他人,我開篇就寫了八位dat,還說用iic,要么給我提些建議,要么直接劃走,說一堆無所謂的話是為了顯示他知道的多嗎?都說了兩塊單片機,dat口,還給我扯到用stc8,說這些有用嗎 |
不明白為什么要單問題覆雜化 1. LCD1602有四線模式的,以你的情況,一個單片機己經可以驅動LCD1602 2. 即使是為了實驗,明明傳一個字節的數據己經足夠,為什么要把4位元數據化為十個字節("LXXXX0000/0")? 3. 就算要傳十個字節,明明有更簡潔的方法,為什么要寫得這么累贅?
|
hhdsdy 發表于 2022-7-17 17:19 正常現象,有的人提問了,你回答的人還得放低自己的姿態去回答,不然,人家不高興 而往往這種問題基本是最終無解的 就拿這個問題來說,一開始樓主的目的是想知道"兩個單片機控制一個LCD"的 現在看來,這個問題顯然已經不重要了,重心已經變成了"誰才是失去了對新鮮事物接受能力的人" 還好沒有說我老,他要是說我老了,我就會很傷心的,因為這是事實,我真是個老頭子,老頭子最怕別人說自己是老頭子 |
美琴的備胎 發表于 2022-7-17 15:26 1:標題根本未提及用并行數據口,正文有但是是不成功的,也未強調必須用并行。 2:10樓的只是表達自己的看法,我是看不出有什么冷嘲熱諷的,你指出來看看? 3:在1樓你并未詳細說明,壇友們給個更合理的建議有什么奇怪的,誰知道你方案定死打板驗證了?反過來嘲笑壇友“失去了對新鮮事物的接受能力”,不知道你這方案有多大的優勢是多么的新鮮?這又是求助于人的態度嗎? 4:不知道拿玩單片機5年來說事有什么意義,回答的壇友們我估計玩單片機比你時間長的多的是,有什么好得意的?而且,玩單片機是否精,并不一定和年限掛鉤,我看了一下你的主題,反而是發帖求助的居多,還不是早年間的 |
美琴的備胎 發表于 2022-7-17 15:23 你說對新事物的探索欲? 那你要給個"誘惑"出來啊 你這樣做的好處是什么?"探索欲"前提是"提高和進步"我現在能通過你這個"靈光一閃"所假象到的任何"好處",都一一被否決了,我如何產生你所謂的"探索欲"?你知道串口通信要耗費多少時間么?要耗費多少io么?要耗費多少內存么?最后達到的效果呢? 加快了速度?沒有,節約了io?沒有,減少了成本?也沒有!怎么算都是入不敷出的投資,這何來探索欲? |
美琴的備胎 發表于 2022-7-17 15:26 所謂"冷嘲熱諷",只是你個人看法,我不帶感情回復,這只是技術問題而已 所謂"難道你已經失去了對新鮮事物的接受能力?開始墨守陳規了?" 我不知道什么叫新鮮事物,如果說是把一件簡單的事情復雜化也算是新鮮事物,那么,我承認,你這確實是很新鮮 把原本可以用一個單片機能做的事,分成兩個單片機來做,這就叫創新? 墨守陳規,我并不是,我剛剛來論壇的時候,99SE還不會用,現在我會AD了 以前我是匯編的,現在我會C了,從開始有學STM32的想法,到入門STM32,我有了想法就去實現了 這是我幾個月前的帖子,那個時候,我還不知道STM32庫函數是怎么回事http://www.zg4o1577.cn/bbs/dpj-218698-1.html 這是我學了二十多天STM32之后的回復,這個時候,我已經開始可以幫助別人解答問題了 http://www.zg4o1577.cn/bbs/dpj-219967-1.html 我不是說我有多牛,我只想說明 ,我多少還是有著上進的心態的,還是有著學習的心態的 那我就在想:為什么非得要兩個stc12c60s2去控制一個LCD不可呢? stc12c60s2是比較久的單片機了?那我可不可以用STC8A8K來代替呢,后者有更多的串口,有內置上拉電阻,12位ADC,而且價格更便宜,貨源也更穩定 在數據處理方便,為什么一定要兩個單片機來做呢?為什么你不把整個項目的大概要求說一下,也許有更好的辦法呢? 可以看出來,墨守陳規的人是你而已 至于你知不知道IIC,我不評論,那是你自己說的 對于幫助,并不是說你要代碼就給代碼,你要電路就給電路,那才叫幫助 你可以把不涉及商業機密的東西說一下,整個項目大概的要求,為什么要兩個單片機?為什么不用IIC說一下 在一個電路中用兩個單片機的,并不是什么新鮮事,那我就在想,可不可以把功能稍稍改一下,只用一個單片機來控制LCD呢? 我知道那么多字,你估計就是一眼掃過而已,不會認真看,這不重要,我就單純的無聊而已,打發一下時間而已 |
wulin 發表于 2022-7-17 14:20 我的必要理由就是必須用兩個單片機并行通信。你說的公用一個晶振可能會有效果? |
Y_G_G 發表于 2022-7-17 14:56 我玩單片機已經五年了,你說的iic我會不知道?我的標題已經說的很清楚了,是用并行數據口,如果你不愿意提供幫助,大可一笑而過,劃出去。為什么要對我冷嘲熱諷?難道你已經失去了對新鮮事物的接受能力?開始墨守陳規了? |
188610329 發表于 2022-7-17 14:32 首先,端口數算是個筆誤。其次,這也不是一拍腦門的想法,從dat端口的io口分離,到串口通信,PCB設計,焊接,用了一周的時間。如果你非要認為是天馬行空,或者一拍腦門,那我也覺得我的付出是值得的。至少我真的為此做出了努力。反倒是你們,不知道年紀多大了,做什么工作,是不是缺少了一些對新鮮事物的探索欲? |
玩了很久的單片機,多多少少還是會一點點的 想了半天,實在是找不到要用兩個單片機控制一個LCD的理由 1,如果是DIY,隨便找一個IIC控制的LCD的直接用OLED不就行了? 2,如果是產品,不知道項目經理是干什么的?一個LCD1602能顯示多少東西?需要用兩個單片機去控制?兩個單片機的資源在很多情況下,都能找到另一個型號的單片機來代替,比如串口,A單片機只有一個串口,那我肯定能找到有兩個串口的單片機 從以往的經驗分析,8051+LCD1602應該是一個DIY作品或者是測試架之類的,直接找一個IIC控制的LCD它不行嗎? |
樓主這是在天馬行空,做項目還是要腳踏實地,等雇了一群程序員給你打下手,再琢磨這些一拍腦門的想法吧,為什么說你是一拍腦門呢?你看看你自己提出的想法: a單片機的p0.0-0.4控制lcd1602 dat的低四位,b單片機的p0.0-0.4控制lcd1602 dat的高四位。 十個io,控制高低8位? 你自己真的仔細思考過,架構過,研究過,實驗過這個設想么? 別說什么特殊需要,沒有一個需要是需要這樣來協同控制得。 |
美琴的備胎 發表于 2022-7-17 11:46 既然這樣做你有特殊的必要性,應該是能夠解決的。 1.如端口不夠用可改4線驅動。 2.如沒有一組完整端口可由任意端口組合。 3.兩個單片機通過串口通訊很難滿足1602對時序的要求。可以考慮兩個單片機共用一個外部時鐘,用中斷+簡單的串行通訊傳輸數據。 |
fgfd 發表于 2022-7-17 10:22 我也知道一個單片機好弄啊,我有特殊的必要性 |
wulin 發表于 2022-7-17 08:03 我也知道一個單片機好弄啊,我有特殊的必要性 |
為啥要接兩個單片機呢?如果想做雙機通信的話,可以把1602接到主機上,數據在從機發啊。 |
用兩塊單片機共同控制一塊lcd1602實施起來很困難,實在想不出這樣做的必要性,樓主要畫蛇添足??? |
思路本身就錯了,兩個單片機很難滿足1602的時序要求,一個單片機可以輕松做到。 |
主機 /*************** 用戶定義參數 *****************************/ #define MAIN_Fosc 22118400L //define main clock #define Baudrate1 9600 //define the baudrate, 如果使用BRT做波特率發生器,則波特率跟串口2一樣 //12T mode: 600~115200 for 22.1184MHZ, 300~57600 for 11.0592MHZ #define Baudrate2 9600 //define the baudrate2, //12T mode: 600~115200 for 22.1184MHZ, 300~57600 for 11.0592MHZ #define BUF_LENTH 128 //定義串口接收緩沖長度 /**********************************************************/ #include<reg51.h> #include<intrins.h> //包含_nop_()函數定義的頭文件 #include<fun.h> sfr AUXR1 = 0xA2; sfr AUXR = 0x8E; sfr S2CON = 0x9A; //12C5A60S2雙串口系列 sfr S2BUF = 0x9B; //12C5A60S2雙串口系列 sfr IE2 = 0xAF; //STC12C5A60S2系列 sfr BRT = 0x9C; unsigned char uart1_wr; //寫指針 unsigned char uart1_rd; //讀指針 unsigned char xdata RX1_Buffer[BUF_LENTH]; bit B_TI; unsigned char uart2_wr; //寫指針 unsigned char uart2_rd; //讀指針 unsigned char xdata RX2_Buffer[BUF_LENTH]; bit B_TI2; /****************** 編譯器自動生成,用戶請勿修改 ************************************/ #define T1_TimerReload (256 - MAIN_Fosc / 192 / Baudrate1) //Calculate the timer1 reload value at 12T mode #define BRT_Reload (256 - MAIN_Fosc / 12 / 16 / Baudrate2) //Calculate BRT reload value #define TimeOut1 (28800 / (unsigned long)Baudrate1 + 2) #define TimeOut2 (28800 / (unsigned long)Baudrate2 + 2) #define TI2 (S2CON & 0x02) != 0 #define RI2 (S2CON & 0x01) != 0 #define CLR_TI2() S2CON &= ~0x02 #define CLR_RI2() S2CON &= ~0x01 /******LCD1602***********/ sbit p00=P0^0; sbit p01=P0^1; sbit p02=P0^2; sbit p03=P0^3; sbit p04=P0^4; sbit p05=P0^5; sbit p06=P0^6; sbit RS=P2^6; //寄存器選擇位,將RS位定義為P2.6引腳 sbit RW=P2^5; //讀寫選擇位,將RW位定義為P2.5引腳 sbit E=P2^7; //使能信號位,將E位定義為P2.7引腳 sbit BF=P0^7; //忙碌標志位,,將BF位定義為P0.7引腳 sbit tx=P2^0; //從機狀態線 sbit rx=P2^1; //從機狀態線 unsigned char flag1,flag2,flag3,flag4;//發送指令位的值 /***************************************************** 函數功能:延時1ms (3j+2)*i=(3×33+2)×10=1010(微秒),可以認為是1毫秒 ***************************************************/ void delay1ms() { unsigned char i,j; for(i=0;i<10;i++) for(j=0;j<33;j++) ; } /***************************************************** 函數功能:延時若干毫秒 入口參數:n ***************************************************/ void delay(unsigned char n) { unsigned char i; for(i=0;i<n;i++) delay1ms(); } /***************************************************** 函數功能:判斷液晶模塊的忙碌狀態 返回值:result。result=1,忙碌;result=0,不忙 ***************************************************/ unsigned char BusyTest(void) { bit result; RS=0; //根據規定,RS為低電平,RW為高電平時,可以讀狀態 RW=1; E=1; //E=1,才允許讀寫 _nop_(); //空操作 _nop_(); _nop_(); _nop_(); //空操作四個機器周期,給硬件反應時間 result=BF; //將忙碌標志電平賦給result E=0; return result; } /***************************************************** 函數功能:將模式設置指令或顯示地址寫入液晶模塊 入口參數:dictate ***************************************************/ void WriteInstruction (unsigned char dictate) { flag1=0;flag2=0;flag3=0;flag4=0; // while(BusyTest()==1); //如果忙就等待 RS=0; //根據規定,RS和R/W同時為低電平時,可以寫入指令 RW=0; E=0; //E置低電平(根據表8-6,寫指令時,E為高脈沖, // 就是讓E從0到1發生正跳變,所以應先置"0" _nop_(); _nop_(); //空操作兩個機器周期,給硬件反應時間 //P0=dictate; //將數據送入P0口,即寫入指令或地址 if((dictate & 0x10 )){ flag1=1; }else {flag1=0;} if((dictate & 0x20 )){ flag2=1; }else {flag2=0;} if((dictate & 0x40 )){ flag3=1; }else {flag3=0;} if((dictate & 0x80 )){ flag4=1; }else {flag4=0;} tx=0; //可以執行下步 delay(30); if(flag1==1&&flag2==1&&flag3==1&&flag4==1) {PrintString1("L111100000");} else if(flag1==0&&flag2==1&&flag3==1&&flag4==1) {PrintString1("L011100000");} else if(flag1==1&&flag2==0&&flag3==1&&flag4==1) {PrintString1("L101100000");} else if(flag1==0&&flag2==0&&flag3==1&&flag4==1) {PrintString1("L001100000");} else if(flag1==1&&flag2==1&&flag3==0&&flag4==1) {PrintString1("L110100000");} else if(flag1==0&&flag2==1&&flag3==0&&flag4==1) {PrintString1("L010100000");} else if(flag1==1&&flag2==0&&flag3==0&&flag4==1) {PrintString1("L100100000");} else if(flag1==0&&flag2==0&&flag3==0&&flag4==1) {PrintString1("L000100000");} else if(flag1==1&&flag2==1&&flag3==1&&flag4==0) {PrintString1("L111000000");} else if(flag1==0&&flag2==1&&flag3==1&&flag4==0) {PrintString1("L011000000");} else if(flag1==1&&flag2==0&&flag3==1&&flag4==0) {PrintString1("L101000000");} else if(flag1==0&&flag2==0&&flag3==1&&flag4==0) {PrintString1("L001000000");} else if(flag1==1&&flag2==1&&flag3==0&&flag4==0) {PrintString1("L110000000");} else if(flag1==0&&flag2==1&&flag3==0&&flag4==0) {PrintString1("L010000000");} else if(flag1==1&&flag2==0&&flag3==0&&flag4==0) {PrintString1("L100000000");} else if(flag1==0&&flag2==0&&flag3==0&&flag4==0) {PrintString1("L000000000");} delay(30); //等待從機將信號置零 tx=1; while(rx==1); //如果從機已執行完 // delay(80); if((dictate & 0x01 )){ p00=1; }else {p00=0;} if((dictate & 0x02 )){ p01=1; }else {p01=0;} if((dictate & 0x04 )){ p02=1; }else {p02=0;} if((dictate & 0x08 )){ p03=1; }else {p03=0;} _nop_(); _nop_(); _nop_(); _nop_(); //空操作四個機器周期,給硬件反應時間 E=1; //E置高電平 _nop_(); _nop_(); _nop_(); _nop_(); //空操作四個機器周期,給硬件反應時間 E=0; //當E由高電平跳變成低電平時,液晶模塊開始執行命令 } /***************************************************** 函數功能:指定字符顯示的實際地址 入口參數:x ***************************************************/ void WriteAddress(unsigned char x) { WriteInstruction(x|0x80); //顯示位置的確定方法規定為"80H+地址碼x" } /***************************************************** 函數功能:將數據(字符的標準ASCII碼)寫入液晶模塊 入口參數:y(為字符常量) ***************************************************/ void WriteData(unsigned char y) { flag1=0;flag2=0;flag3=0;flag4=0; // while(BusyTest()==1); RS=1; //RS為高電平,RW為低電平時,可以寫入數據 RW=0; E=0; //E置低電平(根據表8-6,寫指令時,E為高脈沖, // 就是讓E從0到1發生正跳變,所以應先置"0" //P0=0x23; //將數據送入P0口,即將數據寫入液晶模塊 if(y & 0x10 ){ flag1=1; }else {flag1=0;} if(y & 0x20 ){ flag2=1; }else {flag2=0;} if(y & 0x40 ){ flag3=1; }else {flag3=0;} if(y & 0x80 ){ flag4=1; }else {flag4=0;} /* if((y & 0x10 )){ p04=1; }else {p04=0;} if((y & 0x20 )){ p05=1; }else {p05=0;} if((y & 0x40 )){ p06=1; }else {p06=0;} if((y & 0x80 )){ BF=1; }else {BF=0;} */ tx=0; //可以執行下步 delay(30); if(flag1==1&&flag2==1&&flag3==1&&flag4==1) {PrintString1("L111100000");} else if(flag1==1&&flag2==1&&flag3==1&&flag4==0) {PrintString1("L111000000");} else if(flag1==1&&flag2==1&&flag3==0&&flag4==1) {PrintString1("L110100000");} else if(flag1==1&&flag2==1&&flag3==0&&flag4==0) {PrintString1("L110000000");} else if(flag1==1&&flag2==0&&flag3==1&&flag4==1) {PrintString1("L101100000");} else if(flag1==1&&flag2==0&&flag3==1&&flag4==0) {PrintString1("L101000000");} else if(flag1==1&&flag2==0&&flag3==0&&flag4==1) {PrintString1("L100100000");} else if(flag1==1&&flag2==0&&flag3==0&&flag4==0) {PrintString1("L100000000");} else if(flag1==0&&flag2==1&&flag3==1&&flag4==1) {PrintString1("L011100000");} else if(flag1==0&&flag2==1&&flag3==1&&flag4==0) {PrintString1("L011000000");} else if(flag1==0&&flag2==1&&flag3==0&&flag4==1) {PrintString1("L010100000");} else if(flag1==0&&flag2==1&&flag3==0&&flag4==0) {PrintString1("L010000000");} else if(flag1==0&&flag2==0&&flag3==1&&flag4==1) {PrintString1("L001100000");} else if(flag1==0&&flag2==0&&flag3==1&&flag4==0) {PrintString1("L001000000");} else if(flag1==0&&flag2==0&&flag3==0&&flag4==1) {PrintString1("L000100000");} else if(flag1==0&&flag2==0&&flag3==0&&flag4==0) {PrintString1("L000000000");} delay(30); tx=1; while(rx==1); // delay(80); if((y & 0x01 )){ p00=1; }else {p00=0;} if((y & 0x02 )){ p01=1; }else {p01=0;} if((y & 0x04 )){ p02=1; }else {p02=0;} if((y & 0x08 )){ p03=1; }else {p03=0;} _nop_(); _nop_(); _nop_(); _nop_(); //空操作四個機器周期,給硬件反應時間 E=1; //E置高電平 _nop_(); _nop_(); _nop_(); _nop_(); //空操作四個機器周期,給硬件反應時間 E=0; //當E由高電平跳變成低電平時,液晶模塊開始執行命令 } /***************************************************** 函數功能:對LCD的顯示模式進行初始化設置 ***************************************************/ void InitLCD1602(void) { delay(200); //延時15ms,首次寫指令時應給LCD一段較長的反應時間 WriteInstruction(0x38); //顯示模式設置:16×2顯示,5×7點陣,8位數據接口 delay(200); //延時5ms WriteInstruction(0x38); delay(200); WriteInstruction(0x38); //0x38 delay(200); WriteInstruction(0x0f); //顯示模式設置:顯示開,有光標,光標閃爍 delay(200); WriteInstruction(0x06); //顯示模式設置:光標右移,字符不移 delay(200); WriteInstruction(0x01); //清屏幕指令,將以前的顯示內容清除 delay(200); } /**********************************************************/ void main(void) { delay(1000); uart1_init(); uart2_init(); InitLCD1602();//調用LCD初始化函數 uart1_rd = 0; uart1_wr = 0; uart2_rd = 0; uart2_wr = 0; // AUXR |= 0x01; //串口1使用獨立波特率發生器, 波特率跟串口2一樣 // AUXR1 |= (1<<4); //將UART2從P1口切換到 RXD2--P1.2切換到P4.2 TXD2---P1.3切換到P4.3 while(1) { /* if(uart1_rd != uart1_wr) //串口0轉發 { UART1_TxByte(RX1_Buffer[uart1_rd]); if(++uart1_rd >= BUF_LENTH) uart1_rd = 0; } if(uart2_rd != uart2_wr) //串口2轉發 { UART2_TxByte(RX2_Buffer[uart2_rd]); if(++uart2_rd >= BUF_LENTH) uart2_rd = 0; } */ // PrintString1("123456789+"); // delay1(); WriteInstruction(0x01);//清顯示:清屏幕指令 delay(300); WriteAddress(0x00); //設置顯示位置為第一行的第5個字 delay(300); WriteData('#'); delay(300); } } void UART1_TxByte(unsigned char dat) { B_TI = 0; SBUF = dat; while(!B_TI); B_TI = 0; } void UART2_TxByte(unsigned char dat) { B_TI2 = 0; S2BUF = dat; while(!B_TI2); B_TI2 = 0; } void PrintString1(unsigned char *puts) //發送一串字符串 { for (; *puts != 0; puts++) UART1_TxByte(*puts); //遇到停止符0結束 } void PrintString2(unsigned char *puts) //發送一串字符串 { for (; *puts != 0; puts++) UART2_TxByte(*puts); //遇到停止符0結束 } void uart1_init(void) { PCON |= 0x80; //UART0 Double Rate Enable SCON = 0x50; //UART0 set as 10bit , UART0 RX enable TMOD &= ~(1<<6); //Timer1 Set as Timer, 12T TMOD = (TMOD & ~0x30) | 0x20; //Timer1 set as 8 bits auto relaod TH1 = T1_TimerReload; //Load the timer TR1 = 1; ES = 1; EA = 1; } /**********************************************/ void UART0_RCV (void) interrupt 4 { if(RI) { RI = 0; RX1_Buffer[uart1_wr] = SBUF; if(++uart1_wr >= BUF_LENTH) uart1_wr = 0; } if(TI) { TI = 0; B_TI = 1; } } /**********************************************/ void uart2_init(void) { AUXR |= (1 << 3); //串口2波特率加倍 S2CON = (S2CON & 0x3f) | (1<<6); //串口2模式1,8位UART,(2^S2SMOD / 32) * BRT溢出率 S2CON |= 1 << 4; //允許串2接收 AUXR |= 1 << 4; //baudrate use BRT BRT = BRT_Reload; IE2 |= 1; //允許串口2中斷 } /**********************************************/ void UART2_RCV (void) interrupt 8 { if(RI2) { CLR_RI2(); RX2_Buffer[uart2_wr] = S2BUF; if(++uart2_wr >= BUF_LENTH) uart2_wr = 0; } if(TI2) { CLR_TI2(); B_TI2 = 1; } } 從機 /*************** 用戶定義參數 *****************************/ #define MAIN_Fosc 22118400L //define main clock #define Baudrate1 9600 //define the baudrate, 如果使用BRT做波特率發生器,則波特率跟串口2一樣 //12T mode: 600~115200 for 22.1184MHZ, 300~57600 for 11.0592MHZ #define Baudrate2 9600 //define the baudrate2, //12T mode: 600~115200 for 22.1184MHZ, 300~57600 for 11.0592MHZ #define BUF_LENTH 10 //定義串口接收緩沖長度 /**********************************************************/ #include <reg51.h> sfr AUXR1 = 0xA2; sfr AUXR = 0x8E; sfr S2CON = 0x9A; //12C5A60S2雙串口系列 sfr S2BUF = 0x9B; //12C5A60S2雙串口系列 sfr IE2 = 0xAF; //STC12C5A60S2系列 sfr BRT = 0x9C; unsigned char uart1_wr; //寫指針 unsigned char uart1_rd; //讀指針 unsigned char xdata RX1_Buffer[BUF_LENTH]; bit B_TI; unsigned char uart2_wr; //寫指針 unsigned char uart2_rd; //讀指針 unsigned char xdata RX2_Buffer[BUF_LENTH]; bit B_TI2; sbit p00=P0^0; sbit p01=P0^1; sbit p02=P0^2; sbit p03=P0^3; sbit p04=P0^4; sbit p05=P0^5; sbit p06=P0^6; sbit tx=P2^0; //從機狀態線 sbit rx=P2^1; //從機狀態線 /****************** 編譯器自動生成,用戶請勿修改 ************************************/ #define T1_TimerReload (256 - MAIN_Fosc / 192 / Baudrate1) //Calculate the timer1 reload value at 12T mode #define BRT_Reload (256 - MAIN_Fosc / 12 / 16 / Baudrate2) //Calculate BRT reload value #define TimeOut1 (28800 / (unsigned long)Baudrate1 + 2) #define TimeOut2 (28800 / (unsigned long)Baudrate2 + 2) #define TI2 (S2CON & 0x02) != 0 #define RI2 (S2CON & 0x01) != 0 #define CLR_TI2() S2CON &= ~0x02 #define CLR_RI2() S2CON &= ~0x01 /**********************************************************/ /******************** 本地函數聲明 ***************/ void uart1_init(void); void uart2_init(void); void UART1_TxByte(unsigned char dat); void UART2_TxByte(unsigned char dat); void PrintString1(unsigned char code *puts); void PrintString2(unsigned char code *puts); void main(void) { uart1_rd = 0; uart1_wr = 0; uart2_rd = 0; uart2_wr = 0; // AUXR |= 0x01; //串口1使用獨立波特率發生器, 波特率跟串口2一樣 // AUXR1 |= (1<<4); //將UART2從P1口切換到 RXD2--P1.2切換到P4.2 TXD2---P1.3切換到P4.3 uart1_init(); uart2_init(); while(1) { //if(tx==0){rx=1;} if((uart1_rd != uart1_wr)&&RX1_Buffer[0]=='1') //串口0轉發 { UART2_TxByte(RX1_Buffer[uart1_rd]); if(++uart1_rd >= BUF_LENTH) uart1_rd = 0; }else if((uart1_rd !=10 /*uart1_wr*/)&&RX1_Buffer[0]=='L'&&tx==0) //串口0轉發 { rx=1; //從機開始執行,主機等待 if(RX1_Buffer[1]=='1'){ p00=1;}else {p00=0;} if(RX1_Buffer[2]=='1'){ p01=1;}else {p01=0;} if(RX1_Buffer[3]=='1'){ p03=1;}else {p03=0;} if(RX1_Buffer[4]=='1'){ p04=1; }else {p04=0;} UART2_TxByte(RX1_Buffer[uart1_rd]); if(++uart1_rd >= BUF_LENTH) uart1_rd = 0; rx=0; //從機已執行完 } if(uart2_rd != uart2_wr) //串口2轉發 { UART1_TxByte(RX2_Buffer[uart2_rd]); if(++uart2_rd >= BUF_LENTH) uart2_rd = 0; } } } void UART1_TxByte(unsigned char dat) { B_TI = 0; SBUF = dat; while(!B_TI); B_TI = 0; } void UART2_TxByte(unsigned char dat) { B_TI2 = 0; S2BUF = dat; while(!B_TI2); B_TI2 = 0; } void PrintString1(unsigned char code *puts) //發送一串字符串 { for (; *puts != 0; puts++) UART1_TxByte(*puts); //遇到停止符0結束 } void PrintString2(unsigned char code *puts) //發送一串字符串 { for (; *puts != 0; puts++) UART2_TxByte(*puts); //遇到停止符0結束 } void uart1_init(void) { PCON |= 0x80; //UART0 Double Rate Enable SCON = 0x50; //UART0 set as 10bit , UART0 RX enable TMOD &= ~(1<<6); //Timer1 Set as Timer, 12T TMOD = (TMOD & ~0x30) | 0x20; //Timer1 set as 8 bits auto relaod TH1 = T1_TimerReload; //Load the timer TR1 = 1; ES = 1; EA = 1; } /**********************************************/ void UART0_RCV (void) interrupt 4 { if(RI) { RI = 0; RX1_Buffer[uart1_wr] = SBUF; if(++uart1_wr >= BUF_LENTH) uart1_wr = 0; } if(TI) { TI = 0; B_TI = 1; } } /**********************************************/ void uart2_init(void) { AUXR |= (1 << 3); //串口2波特率加倍 S2CON = (S2CON & 0x3f) | (1<<6); //串口2模式1,8位UART,(2^S2SMOD / 32) * BRT溢出率 S2CON |= 1 << 4; //允許串2接收 AUXR |= 1 << 4; //baudrate use BRT BRT = BRT_Reload; IE2 |= 1; //允許串口2中斷 } /**********************************************/ void UART2_RCV (void) interrupt 8 { if(RI2) { CLR_RI2(); RX2_Buffer[uart2_wr] = S2BUF; if(++uart2_wr >= BUF_LENTH) uart2_wr = 0; } if(TI2) { CLR_TI2(); B_TI2 = 1; } } |