typedef enum {INPUT, OUTPUT}PortDir;
typedef struct
{
uint8 humiInt;
uint8 humiFra;
int8 tempInt;
uint8 tempFra;
uint8 checkSum;
} AM2302Data;
/*********************************************************************************************************
** function Name: BSP_AM2302_HW_INIT(void)
** hard ware initial
*********************************************************************************************************/
void BSP_AM2302_HW_INIT(void)
{
PINSEL_ConfigPin (3, 7, 0);
//P3.7
GPIO_SetDir(3, (1<<7), GPIO_DIRECTION_OUTPUT);
}
void BSP_AM2302_SetPinDir(PortDir dir)
{
if(dir == INPUT)
GPIO_SetDir(3, (1<<7), GPIO_DIRECTION_INPUT);
else
GPIO_SetDir(3, (1<<7), GPIO_DIRECTION_OUTPUT);
}
/*********************************************************************************************************
** function Name: BSP_AM2302_SetPinValue(uint8 val)
** parameter[in]: val; the value of it is LOW or HIGH
** return: none
*********************************************************************************************************/
void BSP_AM2302_SetPinValue(uint8 val)
{
GPIO_OutputValue(3, (1 << 7),(uint8)val);
}
/*********************************************************************************************************
** function Name: BSP_AM2302_ReadPinLever(void)
** parameter: none
**return: the lever of p3.7(HIGH or LOW)
*********************************************************************************************************/
uint8 BSP_AM2302_ReadPinLever()
{
uint32 tmp;
tmp = GPIO_ReadValue(3);
if(tmp&0x80)
return HIGH;
else
return LOW;
}
void TIM_Waitus1(uint32 time)
{
TIM_TIMERCFG_Type TIM_ConfigStruct;
TIM_MATCHCFG_Type MatchConfigStruct;
TIM_ConfigStruct.PrescaleOption = TIM_PRESCALE_USVAL;
TIM_ConfigStruct.PrescaleValue
= 1;
//Init timer 0, prescale count time of 1000uS
//LPC_TIM2->IR = 0xFFFFFFFF; //clear Interupt
MatchConfigStruct.MatchChannel = 0;
MatchConfigStruct.IntOnMatch = ENABLE;
MatchConfigStruct.ResetOnMatch = ENABLE;
MatchConfigStruct.StopOnMatch = ENABLE;
MatchConfigStruct.ExtMatchOutputType = 0;
MatchConfigStruct.MatchValue = time;
TIM_Init(LPC_TIM2, TIM_TIMER_MODE, &TIM_ConfigStruct);
// Set configuration for Tim_config
TIM_ConfigMatch(LPC_TIM2, &MatchConfigStruct);
TIM_Cmd(LPC_TIM2,ENABLE);
//wait until interrupt flag occur
while(!(LPC_TIM2->IR & 0x01));
TIM_ResetCounter(LPC_TIM2);
}
uint8 BSP_AM2302_ReadByte()
{
uint8 tmp = 0, i;
for(i = 0; i < 8; i++)
{
//every bit start with LOW lever for 50us; here we wait for this end
while( LOW == BSP_AM2302_ReadPinLever());
//then real bit value begin; The HIGH lever lasting 68~75us represents 1,
//while lasting 22~30us represents 0.
TIM_Waitus1(50);
if( HIGH == BSP_AM2302_ReadPinLever())
{ //if it was still HIGH lever after 50us, then 1 is reserved;
//otherwise, 0 is reserved.
//wait for the end of the transmission
while( HIGH == BSP_AM2302_ReadPinLever());
tmp |= (uint8)(1<<(7-i));
}
else
tmp &= (uint8)~(1<<(7-i));
}
return tmp;
}
/*********************************************************************************************************
** Function Name: BSP_AM2302_ReadPinLever(void)
** paramater: dataOut is the output parameter containning the expectation data
** return: 0£orepresent right
** -1: represent crc error
** -2: No response from AM2302
*********************************************************************************************************/
int8 BSP_AM2302_ReadData(AM2302Data* dataOut)
{
int8 ret =0;
int16 tmp = 0;
/*request data*/
BSP_AM2302_SetPinDir(OUTPUT);
BSP_AM2302_SetPinValue(LOW);
TIM_Waitus1( 2000); // delay 2ms
BSP_AM2302_SetPinValue(HIGH);
TIM_Waitus1( 30); // delay 30us
BSP_AM2302_SetPinDir(INPUT);
/*discover the response from slave*/
if( LOW == BSP_AM2302_ReadPinLever())
{
/*wait for the end of the response from slave,*/
//it may last 80us
while(LOW == BSP_AM2302_ReadPinLever());
//it may takes 80us
while(HIGH == BSP_AM2302_ReadPinLever());
/*begin to receive data*/
dataOut->humiInt = BSP_AM2302_ReadByte();
dataOut->humiFra = BSP_AM2302_ReadByte();
dataOut->tempInt = BSP_AM2302_ReadByte();
dataOut->tempFra = BSP_AM2302_ReadByte();
dataOut->checkSum = BSP_AM2302_ReadByte();
if(dataOut->checkSum != (uint8)(dataOut->humiInt+dataOut->humiFra+
(uint8)dataOut->tempInt+dataOut->tempFra))
ret = -1;
}
else
ret = -2;
BSP_AM2302_SetPinDir(OUTPUT);
BSP_AM2302_SetPinValue(HIGH);
/*dataOut convert*/
if(ret == 0)
{
tmp = (dataOut->humiInt&0xf)*256 + (dataOut->humiFra>>4)*16+(dataOut->humiFra&0xf);
dataOut->humiInt = tmp/10;
dataOut->humiFra = tmp%10;
tmp = (dataOut->tempInt&0xf)*256 + (dataOut->tempFra>>4)*16+(dataOut->tempFra&0xf);
//if the high bit is 1, then the temperature is negative
dataOut->tempInt = dataOut->tempInt&0x80? -(tmp/10) : (tmp/10);
dataOut->tempFra = tmp%10;
}
else
{
dataOut->humiInt = 0;
dataOut->humiFra = 0;
dataOut->tempInt = 0;
dataOut->tempFra = 0;
dataOut->checkSum = 0;
}
return ret;
}