|
通用異步串口實現單總線硬件控制器的研究和實現方法(菜農)
轉載本帖應注明雁塔菜地: http://blog.ednchina.com/hotpower/
菜農HotPower@126.com 2008.2.29(四年等一回的日子) 于雁塔菜地
常用的單總線有2大類: 1-Wire和HDQ16
1-Wire和HDQ16都采用單線數據雙向通訊,特別是有些1-Wire系列器件甚至不需電源。
單總線和I2C,SPI相比接線簡單,但時序要求很嚴格,一般采用IO模擬定時器輔助的方法.
做主機其缺點還不太明顯,若作為從機設備時,IO模擬一般還需外部中斷協助.
最大特點是CPU占有率太高.甚至根本無法實現.故雙機之間很少采用單總線通訊,
更別指望一主多從或多主多從通訊.
在TI的HDQ16數據文檔中,有文介紹用通用異步串口實現單總線硬件控制器.
但感覺只是理論推導,實際有處重大(犯罪的)錯誤,故感覺沒經過實戰論證.
也懷疑作者故意隱瞞重點。
因為下波特率為57600,8位數據位,2個停止位時,根本不可能產生190uS以上的低電平.
11*17.3uS=190.3uS不錯,可停止是高電平,故只能(1+8)*17.3uS=155.7uS.
即使使用的UART可以提供16位數據,依然不能成立,為何看完此文后便知.
通用異步串口實現單總線硬件控制器的接線方法很簡單,為防止TXD和RXD線與,
TI采用非門加MOS管實現TXD漏極開路,菜農采用二極管.結果一樣.
這樣加上拉電阻并短接RXD后即構成單總線1-Wire或HDQ16.
一.單總線時序的研究:
單總線一般由3大時序構成(簡化):
1.總線復位
因為在空閑時,總線由上拉電阻拉到高電平,這個狀態很有"物理意義"---對從機充電.
此時從機實際是在等待或休眠狀態,故必須要由外部喚醒.
為保證從機的喚醒和聯接的可靠及加速單線通訊的速率,故需長時間的復位(拉低電平).
使其復位周期和數據周期拉大距離以便區分。
HDQ16的總線復位周期由190uS的低電平和45uS的高電平組成,在高電平期間不需從機應答.
1-Wire的總線復位周期由480uS的低電平和480uS的高電平組成,在高電平期間可從機應答.
1-Wire與HDQ16的最大不同在于總線復位周期里包含從機的應答時序.
2.寫'0'
在空閑中總線被下拉(同步)就表示啟動單總線的數據操作過程的開始.
由于總線被下拉導致通訊而阻塞(線與),故本時序只能作為主機操作過程.讀回數據恒為0.
3.寫'1'
這個操作實際是寫'1'和讀'0'及讀'1'三個時序的綜合.
因為TXD的開漏輸出,故單總線實際就是51的準雙向IO. 只有在此期間方可讀取從機數據。
將寫'0'和寫'1'時序進一步合并后,即可實現單總線讀寫一體化操作.
二.串口時序的研究:
串口一般也由3大時序構成:
1.總線復位(同步)
在空閑中總線被下拉(同步)就表示啟動串口的數據操作過程的開始.即常說的"起始位S".
它也標志了雙方異步過程的同步開始.雙方的計時器也開始計時工作.
2.讀寫數據
由于無硬件同步信號,故雙方必須對每個數據位的周期進行事先約定。數據串D0D1..DX
3.總線釋放(停止)
為了下次(幀)通訊,必須釋放總線。從而留給從機處理時間,寬度可調.
MCU一半都有1,2位停止位,1.5位很少.即常說的"停止位P".
三.UART和1-Wire/Hdq16的不同點和共同之處
從以上分析可以看出它們的共同之處:
1.空閑狀態到工作狀態的切換都是采用拉低總線來喚醒從機以實現同步.(起始位S)
2.每位數據都是由一定寬度的高低電平組成.并嚴格保持一定的有效時間.(數據串D0D1..DX)
3.釋放總線結束表示數據的結束.(停止位P)
最大的不同在于"每幀"UART是多位(5,6,7,8等)數據位,而單總線為一位數據.
當UART數據位串為連續的0或1時,就可組成一位單總線的數據位!!!
即該方法是用數據位數的寬度來湊夠單總線的時序脈寬.
四.實現方法舉例(起始位S為低電平,停止位P為高電平,N為數據位數,B為停止為數)
例S=0,P=1,N=5,B=2)BPS=38400 T="34".6us (HDQ16復位時序)
0x00 ->S 00000 PP 即6T個0,2T個1 波形: 低電平207uS, 高電平69.2uS 周期:276.2uS
例S=0,P=1,N=6,B=1)BPS=38400 T="34".6us (HDQ16復位時序)
0x00 ->S 000001 P 即6T個0,2T個1 波形: 低電平207uS, 高電平69.2uS 周期:276.2uS
例S=0,P=1,N=8,B=2)BPS=38400 T="34".6us (HDQ16復位時序)
0x00 ->S 00000111 PP 即6T個0,5T個1 波形: 低電平207uS, 高電平173uS 周期:380.6uS
例S=0,P=1,N=8,B=2)BPS=38400 T="34".6us (HDQ16復位時序)
0x00 ->S 00000000 PP 即9T個0,2T個1 波形: 低電平311.4uS, 高電平69.2uS 周期:380.6uS
例S=0,P=1,N=8,B=2)BPS=57600 T="17".3us (HDQ16寫'1'/讀'0'/讀'1'時序)
0xfe ->S 01111111 PP 即2T個0,9T個1 波形: 低電平34.6uS, 高電平155.7uS 周期:190.3uS
例S=0,P=1,N=8,B=2)BPS=57600 T="17".3us (HDQ16寫'0'時序)
0xc0 ->S 00000011 PP 即7T個0,4T個1 波形: 低電平121.1uS,高電平69.2uS 周期:190.3uS
例S=0,P=1,N=8,B=1)BPS=9600 T="104us" (1-Wire復位/應答時序)
0xf0 ->S 00001111 P 即5T個0,5T個1 波形: 低電平520uS, 高電平520uS 周期:1040uS
例S=0,P=1,N=6,B=1)BPS=115200 T="8".68us (1-Wire寫'1'/讀'0'/讀'1'時序)
0x3f ->S 111111 P 即1T個0,7T個1 波形: 低電平8.68uS, 高電平60.76uS 周期:69.44uS
例S=0,P=1,N=6,B=1)BPS=115200 T="8".68us (1-Wire寫'0'時序)
0x3f ->S 000000 P 即7T個0,1T個1 波形: 低電平60.76uS, 高電平8.68uS 周期:69.44uS
五.程序實現方法(以硬件調試通過的HDQ16為例)
1.結構配置
LPC_Uart_Config_t Uart1Config = {BD57600, WordLength8, true, false, ParitySelOdd,
false, true, FIFORXLEV2, IER_RBR | IER_RLS,
POLLING_MODE,};
2.HDQ16復位時序
void HDQStart (void);
void HDQStart (void)
{
LPC_INT8U ch;
Uart1Config.BaudRate = BD38400;//改寫波特率用于發送復位信號
UART_Init(UART1);//串口初始化
UART_PutCharByPolling(UART1, 0);//發送低電平311.4uS, 高電平69.2uS
ch = UART_GetCharByPolling(UART1);//清空并監測應答或干擾信號等
Uart1Config.BaudRate = BD57600;//改寫波特率用于發送接收數據
UART_Init(UART1);//串口初始化
}
3.串口收發一體化程序代碼
LPC_INT8U HDQReadWriteByte (LPC_INT8U data)
{
LPC_INT8U i, ch;
LPC_INT8U value = 0;
for (i = 0; i < 8; i ++)
{
if (data & 1)
{
UART_PutCharByPolling(UART1, 0xfe);//1
}
else
{
UART_PutCharByPolling(UART1, 0xc0);//0
}
ch = UART_GetCharByPolling(UART1);
data >>= 1;
value >>= 1;
if (ch > 0xf8)
{
value |= 0x80;
}
}
return value;
}
LPC_INT8U HDQReadWriteWord (LPC_INT16U data)
{
LPC_INT8U i, ch;
LPC_INT16U value;
for (i = 0; i < 16; i ++)
{
if (data & 1)
{
UART_PutCharByPolling(UART1, 0xfe);//1
}
else
{
UART_PutCharByPolling(UART1, 0xc0);//0
}
ch = UART_GetCharByPolling(UART1);
data >>= 1;
value >>= 1;
if (ch > 0xf8)
{
value |= 0x8000;
}
}
return value;
}
4.讀寫應用數據
LPC_INT16U HDQReadWriteData (LPC_INT8U command)
{
//LPC_INT8U valuel;
//LPC_INT8U valueh;
LPC_INT16U value;
HDQStart();//190us
HDQReadWriteByte(command);
// valuel = HDQReadWriteByte(0xff);//收發一體化程序讀要寫'1'
// valueh = HDQReadWriteByte(0xff);//收發一體化程序讀要寫'1'
// value = (valueh << 8) | valuel;
value = HDQReadWriteWord(0xffff);//收發一體化程序讀要寫'1'
return value;
}
5.單總線的協議硬件控制器終成正果
LPC_INT16U data = 0;
data = HDQReadWriteData(0x1c);//讀用戶系列號
由于采用了串口作為單總線的協議硬件控制器,故在傳送期間不怕中斷,時序不會錯亂.
這里主要列舉了菜農本人硬件通過的HDQ16,近日將對1-Wire系列進行硬件測試.
同理可知,SPI硬件模塊也作為單總線的協議硬件控制器,MOSI-TX,MISO-RX |
|
|