全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:3169
推到 Plurk!
推到 Facebook!

8051 UART 及data type 轉換疑問

答題得分者是:taishyang
SG0330
一般會員


發表:1
回覆:5
積分:1
註冊:2015-12-12

發送簡訊給我
#1 引用回覆 回覆 發表時間:2015-12-12 20:52:57 IP:120.109.xxx.xxx 訂閱
板上先進們好
我使用AT89S51用I2C的方式,結合幾個模組在LCD上顯示,可以正常顯示,
老師要我們用藍牙的方式傳輸數據到手機上,並做收發的功能,也就是要具有LCD顯示功能和藍牙傳輸的功能,
若有需要分析,我可以上傳完整一點的程式碼,還請多幫忙,謝謝。

我獨立用LED做為驅動的功能測試,燈號正常執行,這部份是模擬手控51的功能,實體上也能正常運作(加熱器、風扇等)。
我預先設定手機按下某A及B鍵,會回傳一個字元'P'、'Q'給51,當收到字元就做裡面的條件,將SBUF設定成對應的ASCII,此功能可以正常運作。

待解決疑問:
1.模組1的型態轉換功能正常,手機可以看到正常數值,但是套在模組2的型態轉換卻一直出問題,編譯器可以通過編譯,但是執行在電路上LCD不會顯示數據。(程式碼見Q1)
2.我將包含LCD的顯示和判斷條件都是放在主程式的while迴圈裡面,但是有些寫法會影響51的功能運作(程式碼見Q2)

以下是我的程式碼
Q1:
*****************************************************************************************
模組1原型態
[code cpp]
bit Data_read(unsigned char data[5])
U8temp = (data[0] data[1] data[2] data[3]);
if (data[4] == (data[0] data[1] data[2] data[3]))
{
return 1;
}
[/code]
模組1轉換過程
[code cpp]
//將模組讀取到的數據轉成ASCII,發送至手機端
void DataDHT_TX(unsigned char Y)
{
unsigned char buf_Y[2];
unsigned int i;
RI=0;//清除RI
buf_Y[0]=(Y/10) 0x30; //十位
buf_Y[1]=(Y) 0x30; //­個位

for(i=0;i<2;i )
{
SBUF=buf_Y[i];
while(TI==0);
TI=0;
}
}
[/code]
*****************************************************************************************
模組2原型態
[code cpp]
float BH1750_read()
[/code]
模組2轉換過程
[code cpp]
void Da750_TX(unsigned short int Q)
{
unsigned short int Buf_X[4];
unsigned int i;
RI=0;
Buf_X[0]=(Q/1000) 0x30; //千位
Buf_X[1]=(Q00)/100 0x30; //百位
Buf_X[2]=((Q00)0)/10 0x30; //十位
Buf_X[3]=((Q00)0) 0x30;//個位

for(i=0;i<4;i )
{
SBUF=Buf_X[i];
while(TI==0);
TI=0;
}
}
[/code]
*****************************************************************************************
Q2
*****************************************************************************************
[code cpp]
while(1)
{
LCD上顯示模組數據

//自動判斷加熱、冷卻-動作正常
if((dhtbuf[2]>=dcc[0])&&(dhtbuf[2]<=dcc[1]))
{
Heater(1); //加熱關風扇
delay(100);
}
else if ((dhtbuf[2]>=dcc[4])&&(dhtbuf[2]<=dcc[5]))
{
Heater(0); //開風扇關加熱
delay(100);
}
else if((dhtbuf[2]>=dcc[2])&&(dhtbuf[2]<=dcc[3]))
{
Heater(2); //不動作
delay(100);
}
}
[/code]
*****************************************************************************************
UART設定
[code cpp]
// UART
void uart_Init(void) // Baud 9600
{
SCON = 0x50; // Set Mode (8-bit UART) ; Mode1,SM1=1,REN=1
TMOD = 0x20; // Set Mode (8-bit timer with reload);Timer-1,Mode2
TH1 = 0xFD; // Baud 9600¡B11.0592MHZ
TR1 = 1; // Start Timer 1 Running
//IE=0x90; // enable serial port interrupt
}
[/code]
*****************************************************************************************
手控副程式
[code cpp]
//手控副程式
void Heater(unsigned int x)
{
if(x==0)
{
heater = 1; //Heater Close
Fan_1 = Fan_2 = 0; // Fan Open
}
else if(x==1)
{
heater = 0; //Heater Open
Fan_1 = Fan_2 = 1; // Fan Close
}
else if(x==2)
{
heater=Fan_1 = Fan_2=1;
}
}
[/code]
*****************************************************************************************




taishyang
站務副站長


發表:377
回覆:5490
積分:4563
註冊:2002-10-08

發送簡訊給我
#2 引用回覆 回覆 發表時間:2015-12-14 10:09:18 IP:59.127.xxx.xxx 訂閱
設斷點單步執行看看執行到哪有問題吧,沒有你的硬體沒有你的code...

SG0330
一般會員


發表:1
回覆:5
積分:1
註冊:2015-12-12

發送簡訊給我
#3 引用回覆 回覆 發表時間:2015-12-14 10:40:51 IP:120.109.xxx.xxx 訂閱
我下過斷點看過,Q2問題解決,Q1轉換還是不太清楚是不是轉換型態有問題
追加問個問題,我用步進馬達可以控制正、反轉、停止,是用8051獨立接馬達和極限開關做測試
我將這個程式寫成副程式包進另一個I2C LCD的程式裡面
程式可以編譯過,晶片燒錄後LCD功能就不太正常了

[code cpp]
#include
#define motor P0
unsigned char Forward_Motor[]={0x33,0x66,0xcc,0x99}; //正向
unsigned char Reverse_Motor[]={0x99,0xCC,0x66,0x33}; //反向
unsigned char counts=0;

void delay1ms(int);
Forward(void);
Reverse(void);
Stop_Motor(void);

sbit switch1 = P1^0;
sbit switch2 = P1^7;
sbit switch3 = P1^5;

void main()
{
//ok
switch1=1; //when open 8051, open switch signal.
switch2=1; //when open 8051, open switch signal.
motor=0; //when open 8051, close motor signal.
switch3=1;

while(1)//ok
{
if((!switch1)&&(switch2==1)) //ok
{
Forward();
break;
}
else if((!switch2)&&(switch1==1)) //ok
{
Reverse();
break;
}
else if((!switch3)&&(switch1==1)&&(switch2==1))
{
Stop_Motor();
break;
}
}
}

Forward(void) //
{
char j=0;
motor=0;

while(1){
if( counts==5)
{
motor=Forward_Motor[j];
delay1ms(50);
if( j==4) j=0;
counts=0;
}
if(switch3==0) return switch1=switch2=switch3=1; //
}
}

Reverse(void) //«á°h,switch1=1,switch2=0
{
char j=0;
motor=0;

while(1){
if( counts==5)
{
motor=Reverse_Motor[j];
delay1ms(50);
if( j==4) j=0;
counts=0;
}
if(switch3==0) return switch1=switch2=switch3=1; //
}
}

Stop_Motor(void)
{
while(1){
motor=0;
return switch1=switch2=switch3=1; //
}
}

void delay1ms(int x)
{
int i,j;
for(i=0;i for(j=0;j<120;j );
}
[/code]
taishyang
站務副站長


發表:377
回覆:5490
積分:4563
註冊:2002-10-08

發送簡訊給我
#4 引用回覆 回覆 發表時間:2015-12-14 13:37:47 IP:59.127.xxx.xxx 訂閱
下斷點,觀察變數內容應該都可以分析出問題
另外main()裡面的while(1)會因當中switch條件成立而break,預期會有甚麼樣的結果?



SG0330
一般會員


發表:1
回覆:5
積分:1
註冊:2015-12-12

發送簡訊給我
#5 引用回覆 回覆 發表時間:2015-12-14 16:29:27 IP:120.109.xxx.xxx 訂閱
預期的結果,流程大概是這樣:
判斷某數值,呼叫馬達副程式,馬達動作(前進、後退、停止)
[code cpp]
unsigned char Lux_Compare[]={900, 1200, 1500, 2000};
//X=Lux_Value
if(Lux_Value[0]<=Lux_Compare[0]) // 假設當前 X=800,X<900
{
Forward(); // call Forward function
}
else if (Lux_Value[0]>=Lux_Compare[1])&&(Lux_Value[0]<=Lux_Compare[2]) // 假設當前 X=1300,1200
{
Stop_Motor(); // call Stop_Motor function
}
else if(Lux_Value[0]>=Lux_Compare[0]) // 假設當前 X=2100,2000
{
Reverse(); // call Reverse function
}
[/code]
[code cpp]
while(1)//ok
{
if((!switch1)&&(switch2==1))
{
Forward();
break;
}
else if((!switch2)&&(switch1==1))
{
Reverse();
break;
}
else if((!switch3)&&(switch1==1)&&(switch2==1))
{
Stop_Motor();
break;
}
}
[/code]
編輯記錄
SG0330 重新編輯於 2015-12-14 19:07:49, 註解 無‧
SG0330 重新編輯於 2015-12-14 19:08:54, 註解 無‧
SG0330 重新編輯於 2015-12-14 19:11:25, 註解 無‧
taishyang
站務副站長


發表:377
回覆:5490
積分:4563
註冊:2002-10-08

發送簡訊給我
#6 引用回覆 回覆 發表時間:2015-12-14 17:45:24 IP:59.127.xxx.xxx 訂閱
你所有的break都會跳離loop1, 所以條件成立,動作就只會發生一次
while(1) //loop 1
{
if((!switch1)&&(switch2==1)){
Forward();
break;
}else if((!switch2)&&(switch1==1)){
Reverse();
break;
}else if((!switch3)&&(switch1==1)&&(switch2==1)){
Stop_Motor();
break;
}
}

SG0330
一般會員


發表:1
回覆:5
積分:1
註冊:2015-12-12

發送簡訊給我
#7 引用回覆 回覆 發表時間:2015-12-14 19:20:03 IP:120.109.xxx.xxx 訂閱
我明白break會跳脫 loop,那段程式是測試使用的,壓下極限開關就做動
此樓第一串程式是修改後的,這段程式我要加入I2C LCD 這個專案裡面
這三個動作我也是直接引用-> Forward()、Reverse()、Stop_Motor(),分別寫成三個副程式,再用第一串程式去呼叫
目前問題在燒錄完,I2C LCD 顯示會不正常
===================引 用 SG0330 文 章===================
預期的結果,流程大概是這樣:
判斷某數值,呼叫馬達副程式,馬達動作(前進、後退、停止)
[code cpp]
unsigned char Lux_Compare[]={900, 1200, 1500, 2000};
//X=Lux_Value
if(Lux_Value[0]<=Lux_Compare[0]) // 假設當前 X=800,X<900
{
Forward(); // call Forward function
}
else if (Lux_Value[0]>=Lux_Compare[1])&&(Lux_Value[0]<=Lux_Compare[2]) // 假設當前 X=1300,1200
{
Stop_Motor(); // call Stop_Motor function
}
else if(Lux_Value[0]>=Lux_Compare[0]) // 假設當前 X=2100,2000
{
Reverse(); // call Reverse function
}
[/code]
[code cpp]
while(1)//ok
{
if((!switch1)&&(switch2==1))
{
Forward();
break;
}
else if((!switch2)&&(switch1==1))
{
Reverse();
break;
}
else if((!switch3)&&(switch1==1)&&(switch2==1))
{
Stop_Motor();
break;
}
}
[/code]
taishyang
站務副站長


發表:377
回覆:5490
積分:4563
註冊:2002-10-08

發送簡訊給我
#8 引用回覆 回覆 發表時間:2015-12-15 09:40:38 IP:59.127.xxx.xxx 訂閱
怎樣不正常? 有看過I2C信號是否正確嗎?
SG0330
一般會員


發表:1
回覆:5
積分:1
註冊:2015-12-12

發送簡訊給我
#9 引用回覆 回覆 發表時間:2015-12-16 17:22:59 IP:120.109.xxx.xxx 訂閱
個人能力有限, 還不太懂怎麼排除I2C訊號問題
請問先進有什麼比較好的方法可以進一步的追蹤?
taishyang
站務副站長


發表:377
回覆:5490
積分:4563
註冊:2002-10-08

發送簡訊給我
#10 引用回覆 回覆 發表時間:2015-12-17 09:38:06 IP:59.127.xxx.xxx 訂閱
買台LA(如:Zeroplus) 分析信號
SG0330
一般會員


發表:1
回覆:5
積分:1
註冊:2015-12-12

發送簡訊給我
#11 引用回覆 回覆 發表時間:2015-12-19 12:21:48 IP:120.109.xxx.xxx 訂閱
好的, 我會再想方法解決, 謝謝提供資訊
系統時間:2024-04-19 12:15:41
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!