網(wǎng)站:bbs.21ic.com
比如常用的單線協(xié)議的溫濕度傳感器DHT21。
開始讀取時候,假設(shè)傳感器是空閑的,那么這個時候傳感器就是在高電平,主控想要發(fā)起讀取,要給傳感器一個讀取的信號,這個信號就是先拉低至少500us,然后拉高20到40us。
保持20us到40us。
Write_AM2301_PIN_Init();
RESET_AM2301_PIN();
HAL_Delay(2);
SET_AM2301_PIN();
rt_hw_us_delay(30);
讀取相應(yīng),因為接下來器件會主動拉低總線80us,然后再拉高80us.
我們先切換主控的這個IO到輸入模式,進行讀取。然后判斷
器件準備好的這個拉低拉高信號。
第一步,切斷刀輸入模式,準備讀取IO信號
Read_AM2301_PIN_Init();
Sensor_AnswerFlag=0;
判斷是否傳感器拉低了總線,拉低表示傳感器要發(fā)送準備好信號了
=GPIO_PIN_RESET) =
{
Sensor_AnswerFlag=1;
Sys_CNT=0;
while(Read_AM2301_PIN()==GPIO_PIN_RESET)
{
if(++Sys_CNT>3000)
{
Sensor_ErrorFlag=1;
return 0;
}
}
Sys_CNT=0;
while(Read_AM2301_PIN()==GPIO_PIN_SET)
{
if(++Sys_CNT>3000)
{
Sensor_ErrorFlag=1;
return 0;
}
}
每次讀取8BIT,一共5此,所以用個循環(huán)。方到準備好的變量數(shù)組里
for(i=0;i<5;i++)
{
AM2301_Data = Read_AM2301_Data();i>
}</i>
我們看到總線在傳輸數(shù)據(jù)時候,拉低都是50us,只有拉高長短不同,長的表示1,短的表示0.
因此我們讀取每一位時候,只要先判斷是不是低電平或者高電平,就行了。
在低電平時候我們等待,當高電平到來我們判斷是否大于28us,因為26us~28us表示0,70us標志1.
所以我們找一個介于28到70us之間的判斷閾值。
比如我以30us作為閾值,當?shù)碗娖浇Y(jié)束后,我延時30us,如果是0,這個時候高電平肯定結(jié)束了,
如果是1,高電平還在持續(xù)。
因此我通過這個思路判斷是0還是1.
因為我要讀取是8BIT,因此我用循環(huán)8次的操作。
unsigned char Read_AM2301_Data(void)
{
unsigned char i,cnt,buffer,tmp;
//要讀取8次
for (i = 0; i < 8; i++)
{
cnt=0;
//判斷低電平是否結(jié)束
while(!Read_AM2301_PIN())
{
if(++cnt>=3000)
break;
}
//低電平結(jié)束后,進入高電平,開始計時30us
rt_hw_us_delay(30);
tmp=0;
//如果此時還是高電平,那么肯定是大于28us,確定是1來了,賦值1
if(Read_AM2301_PIN())
tmp=1;
cnt=0;
//等待高電平結(jié)束,號進入下一位的讀取
while(Read_AM2301_PIN())
{
if(++cnt>=2000)
break;
}
//移位寫入剛剛得到的1個BIT
buffer<<=1;
buffer|=tmp;
}
return buffer;
}
實現(xiàn)讀取IO狀態(tài)和寫高低電平。
unsigned char Read_AM2301_PIN(void)
{
return HAL_GPIO_ReadPin(AM2301_PORT, AM2301_PIN);
}
void SET_AM2301_PIN(void)
{
HAL_GPIO_WritePin(AM2301_PORT, AM2301_PIN,GPIO_PIN_SET);
}
void RESET_AM2301_PIN(void)
{
HAL_GPIO_WritePin(AM2301_PORT, AM2301_PIN,GPIO_PIN_RESET);
}
//讀傳感器 端口位定義,可修改
//*
unsigned char Sensor_AnswerFlag; //收到起始標志位
unsigned char Sensor_ErrorFlag; //讀取傳感器錯誤標志
unsigned int Sys_CNT;
unsigned char AM2301_Data[5]={0x00,0x00,0x00,0x00,0x00};
void Read_AM2301_PIN_Init(void)
{
AM2301_GPIO_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Pin = AM2301_PIN;
HAL_GPIO_Init(AM2301_PORT, &GPIO_InitStruct);
}
void Write_AM2301_PIN_Init(void)
{
AM2301_GPIO_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Pin = AM2301_PIN;
HAL_GPIO_Init(AM2301_PORT, &GPIO_InitStruct);
}
unsigned char Read_AM2301_PIN(void)
{
return HAL_GPIO_ReadPin(AM2301_PORT, AM2301_PIN);
}
void SET_AM2301_PIN(void)
{
HAL_GPIO_WritePin(AM2301_PORT, AM2301_PIN,GPIO_PIN_SET);
}
void RESET_AM2301_PIN(void)
{
HAL_GPIO_WritePin(AM2301_PORT, AM2301_PIN,GPIO_PIN_RESET);
}
unsigned char Read_AM2301_Data(void)
{
unsigned char i,cnt,buffer,tmp;
for (i = 0; i < 8; i++)
{
cnt=0;
while(!Read_AM2301_PIN())
{
if(++cnt>=3000)
break;
}
rt_hw_us_delay(30);
tmp=0;
if(Read_AM2301_PIN())
tmp=1;
cnt=0;
while(Read_AM2301_PIN())
{
if(++cnt>=2000)
break;
}
buffer<<=1;
buffer|=tmp;
}
return buffer;
}
unsigned char Read_Sensor(void)
{
unsigned char i;
Write_AM2301_PIN_Init();
RESET_AM2301_PIN();
// rt_thread_mdelay(2);
HAL_Delay(2);
SET_AM2301_PIN();
rt_hw_us_delay(30);
SET_AM2301_PIN();
Read_AM2301_PIN_Init();
Sensor_AnswerFlag=0;
if(Read_AM2301_PIN()==GPIO_PIN_RESET)
{
Sensor_AnswerFlag=1;
Sys_CNT=0;
while(Read_AM2301_PIN()==GPIO_PIN_RESET)
{
if(++Sys_CNT>3000)
{
Sensor_ErrorFlag=1;
return 0;
}
}
Sys_CNT=0;
while(Read_AM2301_PIN()==GPIO_PIN_SET)
{
if(++Sys_CNT>3000)
{
Sensor_ErrorFlag=1;
return 0;
}
}
for(i=0;i<5;i++)
{
AM2301_Data[i] = Read_AM2301_Data();
}
}
else
{
Sensor_AnswerFlag=0;
}
return 1;
}
本文系21ic論壇網(wǎng)友gaoyang9992006原創(chuàng)
免責聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!