我用STM32读取AM2301温湿度传感器,裸机跑的时候读取正常的,但是运行UCOSII系统后,读取的数据是不对的,就是偶尔有几个数据位不对。类似DS18B20的单总线通信对时序要求很高,不知道是不是因为UCOS系统产生调度的原因。
我在读取温湿度前后加入了 OSSchedLock(); OSSchedUnlock(); 也不能解决问题
void AM2301_task(void *pdata)
{
u8 i;
while(1)
{
OSSchedLock();
AM2301_READ();//读取温湿度数值
OSSchedUnlock();//恢复调度
for(i=0;i<10;i++)
{
delay_ms(1000);
}
}
}
void AM2301_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; //IO口速度为2MHz
GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化
}
void AM2301_IN(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化
}
u8 AM2301_Start(void)
{
u16 count=0;
AM2301_OUT(); //设置端口输出
AM2301_DATOUT = 0;
delay_ms(2); //持续最低1ms
AM2301_IN();
delay_us(35);
count = 0;
while(AM2301_DATIN==0)
{
delay_us(1);
if(count++>500)
{
count = 0;
return 1; //失败
}
}
count = 0;
while(AM2301_DATIN==1)
{
delay_us(1);
if(count++>500)
{
count = 0;
return 1; //失败
}
}
return 0;//成功
}
u8 AM2301_ReadValue(void)
{
u8 i;
u16 count;
u8 data_temp=0;
for(i=0;i<8;i++)
{
data_temp<<=1;
count = 0;
while(AM2301_DATIN==0)
{
delay_us(1);
if(count++>500)
{
count = 0;
return 0xff; //失败
}
}
delay_us(35);
if(AM2301_DATIN==1)
{
data_temp|=1;
}
else
{
data_temp|=0;
}
count = 0;
while(AM2301_DATIN==1)
{
delay_us(1);
if(count++>500)
{
count = 0;
return 0xff; //失败
}
}
}
return data_temp;
}
u8 Get_data(unsigned char *buf)
{
u8 i,j;
u8 databuf1[5];
for(i=0;i<5;i++)
{
j = AM2301_ReadValue();
if(j==0xff)
return 1;//失败
else
databuf1= j;
}
j= databuf1[0]+databuf1[1]+databuf1[2]+databuf1[3];
if(databuf1[4]==j)
{
for(i=0;i<5;i++)
*(buf+i) = databuf1;
//if( *(buf+4) == *(buf+0)+*(buf+1)+*(buf+2)+*(buf+3) )
return 0;
}
else
return 1;
}
u8 AM2301_READ(void)//读取温湿度数值
{
u8 DHTData[5];
u16 tempv;
if(AM2301_Start()==1)
return 1;
if(Get_data(DHTData)==1)
{
return 1;
}
else
{
tempv = (DHTData[2]<<8)+DHTData[3];
if( (tempv&0x8000)==0x8000 )//负数
{
Temp_value = -( (tempv&0x7fff)/10 + ((tempv&0x7fff)%10)*0.1);
}
else
{
Temp_value = tempv/10 + (tempv%10)*0.1;
}
tempv = (DHTData[0]<<8)+DHTData[1];
Hum_value = tempv/10 + (tempv%10)*0.1;
return 0;
}
}
//延时nus
//nus为要延时的us数.
void delay_us(u32 nus)
{
u32 ticks;
u32 told,tnow,tcnt=0;
u32 reload=SysTick->LOAD; //LOAD的值
ticks=nus*fac_us; //需要的节拍数
tcnt=0;
told=SysTick->VAL; //刚进入时的计数器值
while(1)
{
tnow=SysTick->VAL;
if(tnow!=told)
{
if(tnow<told)tcnt+=told-tnow;//这里注意一下SYSTICK是一个递减的计数器就可以了.
else tcnt+=reload-tnow+told;
told=tnow;
if(tcnt>=ticks)break;//时间超过/等于要延迟的时间,则退出.
}
};
}
//延时nms
//nms:要延时的ms数
void delay_ms(u16 nms)
{
if(OSRunning==TRUE)//如果os已经在跑了
{
if(nms>=fac_ms)//延时的时间大于ucos的最少时间周期
{
OSTimeDly(nms/fac_ms);//ucos延时
}
nms%=fac_ms; //ucos已经无法提供这么小的延时了,采用普通方式延时
}
delay_us((u32)(nms*1000)); //普通方式延时,此时ucos无法启动调度.
}
|