说明:mini2440平台,wince6.0系统,vs2005
经过几个月的学学停停,终于在wince下加入了GPIO模拟的IIC总线,实现了IIC的移植,IIC的芯片是SHT21温湿度芯片。
之所以搞了这么久没搞定IIC,是在ADS下很早实现了,可就是添加到系统就总不对!示波器抓取发现时序在芯片复位后就不对了,找来找去都不知道怎么回事!这下就陷入了
纠结中,还是那种死循环的纠结,怎么都绕不出来!
网上发帖,网友们也支了很多招,感谢你们!jonsenwu网友的话提示了我!驱动程序加到系统里面,系统的调度需要时间,驱动程序使用的延时会出现延长的情况!根据他的提示,也进一步向他请教,这里特别感谢他!对驱动程序的优先级进行调整,使其在运行过程中始终保持住CPU的使用权。在ADS下测试的延时函数在系统下是不会相同的!
经过这个移植学到的东西:
1、wince下优先级相关知识
以下是代码:用于实现优先级抢占
//dwThreadID = GetCurrentThread(); //获取线程的ID
//dwThreadPri = CeGetThreadPriority(dwThreadID); //获取线程ID的优先级
//dwThreadQuantum = CeGetThreadQuantum(dwThreadID); // 获取线程的时间论片参数
//CeSetThreadPriority(dwThreadID, 0);// 设置当前线程的优先级为最高
//CeSetThreadQuantum(dwThreadID, 0); //设置当前线程的时间论片为0,保持CPU的占有权
//
//.......... (操作i2c的函数)
//
//CeSetThreadQuantum(dwThreadID, dwThreadQuantum); // 恢复正常时间论片
//CeSetThreadPriority(dwThreadID, dwThreadPri); //恢复正常优先级
说明:设置优先级有两个函数,一个函数可以设置0~255的个优先级(CeSetThreadPriority()),一个函数可以只能设置应用程序的优先级248~255(SetThreadPriority())!!
IIC调试成功后,把数据传给应用程序又出现个问题,先是在XXX_IOControl实现传递,怎么试都没数据出来,最后放到XXX_Read里面来实现就OK了。这里还要说明个关于memcpy的问题。如下:
2、对于memcpy函数的理解
先看一下出问题的写法:
unsigned short SHT_Data[2];//
memcpy( pBuffer , SHT_Data , 2 );//output
我应用程序读到的数据只有温度是对的,湿度就很大的数!肯定高手一眼就看出来问题所在了!
是因为:memcpy函数的拷贝是基于字节的,上面我拷贝的个数是2,所以只有温度能正常,湿度根本就没拷贝过去。
正确的方法是4个字节:memcpy( pBuffer , SHT_Data , 4);//output
3、GPIO的说明
这里得再次鄙视下友善之臂的技服!GPIO我原来使用的是2440默认两个引脚(默认的接了EEPROM和Camera!!,能对才怪!),最后查找到SPI0的空余引脚才搞定。
代码可以参照:http://www.linuxidc.com/Linux/2012-11/74419p2.htm
在mini2440下用IIC的IO口的模拟IIC时序,驱动一个外设芯片,ADS调试正确,添加到系统就不行,对驱动的优先级也提升了,还是不正确。
volatile IOPreg *s2440IOP = (IOPreg *)IOP_BASE;
//volatile INTreg *s2440INT = (INTreg *)INT_BASE;
float SHT_Data[2];///tmp
HANDLE hDevSHT21;
DWORD SHT2x_Option_ThreadFuc(LPVOID Context);
void Virtual_Alloc(); // Virtual allocation
///////////////////////////////////////////////////////////////////////////
////////////////////////////////I2C.c source///////////////////////////////////////
#define noACK 0
#define aCk 1
#define SCL_OutEnable s2440IOP->rGPECON =( s2440IOP->rGPECON | 0x30000000 ) & 0xDFFFFFFF //28 config SCL as output
#define SDA_OutEnable s2440IOP->rGPECON =( s2440IOP->rGPECON | 0xC0000000 ) & 0x7FFFFFFF //30config SDA as output
#define SDA_OutDisable s2440IOP->rGPECON =( s2440IOP->rGPECON & 0x3fffffff)//config SDA as input
#define SCL_Set s2440IOP->rGPEDAT |= (1 << 14) //SCL output "1"
#define SCL_Clear s2440IOP->rGPEDAT &= ~(1 << 14) //SCL output "0"
#define SDA_Set s2440IOP->rGPEDAT |= (1 << 15) //SDA output "1"
#define SDA_Clear s2440IOP->rGPEDAT &= ~(1 << 15)
void Delay_us(U32 uS)
{
volatile DWORD dwCounter;
dwCounter = 100 * uS;
while(dwCounter--);
}
void I2c_Initialize ()
{ // put setup code here
SCL_OutEnable; // set gpio6->SCL as output
SCL_Set; // set SCL = "1"
SDA_OutDisable; // set gpio7->SDA as input
SDA_Set;
Delay_us(100); // let I2C device ready
}
//==============================================================================
void I2c_StartCondition ()
//==============================================================================
{
SDA_OutEnable; // set SDA as output
//SCL_OutEnable; //!!
SDA_Set;
SCL_Set;
Delay_us(1);
SDA_Clear;
Delay_us(5);
SCL_Clear;
Delay_us(5);
}
//==============================================================================
void I2c_StopCondition ()
//==============================================================================
{
SDA_OutEnable; // set SDA as output
//SCL_OutEnable; //!!
SDA_Clear;
SCL_Clear;
Delay_us(1);
SCL_Set;
Delay_us(5);
SDA_Set;
Delay_us(5);
}
//----------------------------------------------------------------------------------
unsigned char I2c_WriteByte(unsigned char value)
// writes a byte on the Sensibus and checks the acknowledge
//----------------------------------------------------------------------------------
{
// dwThreadID = GetCurrentThread();
//dwThreadPri = CeGetThreadPriority(dwThreadID);
//dwThreadQuantum = CeGetThreadQuantum(dwThreadID);
//CeSetThreadPriority(dwThreadID, 0);/
//CeSetThreadQuantum(dwThreadID, 0);
//
//。。。。。。。 (此部分是操作i2c的函数)
//
//CeSetThreadQuantum(dwThreadID, dwThreadQuantum);
//CeSetThreadPriority(dwThreadID, dwThreadPri);
HANDLE dwThreadID = GetCurrentThread();
DWORD dwThreadPri = CeGetThreadPriority(dwThreadID);
DWORD dwThreadQuantum = CeGetThreadQuantum(dwThreadID);
CeSetThreadPriority(dwThreadID, 0);
CeSetThreadQuantum(dwThreadID, 0);
int error=0, i1=0, i2=0;
for(i2 = 0; i2 < 8; i2++ )
{ // setup data onto SDA
if(value & 0x80){
SDA_Set; //SetSDA( 1 );
}
else{
SDA_Clear; //SetSDA( 0 );
}
Delay_us(1); //I2C timing: data setup time > 200ns
// issue a clock
SCL_Set; //SetSCL( 1 );
Delay_us(1); //I2C timing: SCL high time > 0.6us
SCL_Clear; //SetSCL( 0 );
Delay_us(2); //I2C timing: SCL low time > 1.3us
value= value<< 1;
}
//check ACK(Low state) from I2C device
SDA_OutDisable; //set SDA as input
Delay_us(1); //I2C timing: data(from I2C device) setup time > 200ns
SCL_Set; //SetSCL( 1 ); // issue a clock
Delay_us(1); //I2C timing: SCL high time > 0.6us
if(s2440IOP->rGPEDAT>>15) //read ACK_BIT issued from I2C device
{
// NO ACK, so setup STOP condition
SCL_Set; //SetSCL( 1 );
Delay_us(1); //I2C timing: stop setup timing > 0.6us
SDA_Set; //SetSDA( 1 ); SDA is in input status!
return -(i1+1); // no acknowledgement -> failed
}
SCL_Clear; //SetSCL( 0 );
Delay_us(2); //I2C timing: SCL low time > 1.3us
//check ACK passed, config SDA as output for further outputing
SDA_OutEnable;
// backup the thread priority;
CeSetThreadQuantum(dwThreadID, dwThreadQuantum);
CeSetThreadPriority(dwThreadID, dwThreadPri);
return 0;
}
//----------------------------------------------------------------------------------
unsigned char I2c_ReadByte(unsigned char ack)
//----------------------------------------------------------------------------------
// reads a byte form the Sensibus and gives an acknowledge in case of "ack=1"
{
HANDLE dwThreadID = GetCurrentThread();
DWORD dwThreadPri = CeGetThreadPriority(dwThreadID);
DWORD dwThreadQuantum = CeGetThreadQuantum(dwThreadID);
CeSetThreadPriority(dwThreadID, 0);
CeSetThreadQuantum(dwThreadID, 0);
unsigned char i,val=0;
int i2=0,ub[1];
SDA_OutDisable; //SetSDADir( 0 ); // set SDA as input
// then read a abyte
for(i2 = 0; i2 < 8; i2++)
{
ub[0] = ub[0] << 1;
// issue a clock
SCL_Set; //SetSCL( 1 );
//DelayInuSec(1); //I2C timing: SCL high time > 0.6us
if(s2440IOP->rGPEDAT>>15) // read SDA
{
ub[0] = ub[0] | 0x01;
}
SCL_Clear; //SetSCL( 0 );
Delay_us(5); //I2C timing: SCL low time > 1.3us
}
//issue ACK condition properly
SDA_OutEnable;
if (ack)
{ SDA_Clear; }
else
{ SDA_Set; }
Delay_us(1); //I2C timing: data setup time > 200ns
SCL_Set; //SetSCL( 1 );
Delay_us(1); //I2C timing: SCL high time > 0.6us
SCL_Clear;
Delay_us(2); //I2C timing: SCL low time > 1.3us
// backup the thread priority;
CeSetThreadQuantum(dwThreadID, dwThreadQuantum);
CeSetThreadPriority(dwThreadID, dwThreadPri);
return ub[0];
}
///////////////////////////// SHT2x.c source //////////////////////////////////////
//===========================================================================
unsigned char SHT2x_MeasureHM(etSHT2xMeasureType eSHT2xMeasureType, unsigned int *pMeasurand)
//===========================================================================
{
unsigned char checksum; //checksum
unsigned char data[2]; //data array for checksum verification
unsigned char error=0; //error variable
unsigned int i; //counting variable
//-- write I2C sensor address and command --
I2c_StartCondition();
error |= I2c_WriteByte (I2C_ADR_W); // I2C Adr 0x80
RETAILMSG(1,(TEXT(" ...I2c_WriteByte (I2C_ADR_W ) error=%d rn"),error));
error = 0;
switch(eSHT2xMeasureType)
{
case HUMIDITY:
error |= I2c_WriteByte (TRIG_RH_MEASUREMENT_HM); break; //0xe5
case TEMP :
error |= I2c_WriteByte (TRIG_T_MEASUREMENT_HM); break; //0xe3
default:
break;
}
//-- wait until hold master is released --
RETAILMSG(1,(TEXT(" ...The MEASUREMENT error=%d rn"),error));
error = 0;
I2c_StartCondition();
error |= I2c_WriteByte (I2C_ADR_R);//0x81
RETAILMSG(1,(TEXT(" ...I2c_WriteByte (I2C_ADR_R) error =%d rn"),error));
error = 0;
Delay_us(2400);//covert time 90ms
//-- read two data bytes and one checksum byte --
data[0] = I2c_ReadByte(ACK);
data[1] = I2c_ReadByte(ACK);
checksum=I2c_ReadByte(NO_ACK);
RETAILMSG(1,(TEXT(" ...the MSB is 0x%xrn"), data[0]));
RETAILMSG(1,(TEXT(" ...the LSB is 0x%xrn"), data[1]));
*pMeasurand=data[0];
*pMeasurand<<=8;
*pMeasurand+=data[1];
//-- verify checksum --
//error |= SHT2x_CheckCrc (data,2,checksum);
I2c_StopCondition();
return error;
}
//===========================================================================
u8 SHT2x_SoftReset()
//===========================================================================
{
u8 error=0; //error variable
I2c_StartCondition();
error |= I2c_WriteByte (I2C_ADR_W); // I2C Adr 0x80
error |= I2c_WriteByte (SOFT_RESET); //0xfe // Command
I2c_StopCondition();
//Delay_us(400); // wait till sensor has restarted
Sleep(15);
return error;
}
//void SHT2x_Option(unsigned int pValue[] )
DWORD SHT2x_Option_ThreadFuc(LPVOID Context)
{
int error=0;
unsigned int sRH,sT;
float fHumiValue,fTempeValue;
LPCRITICAL_SECTION RegCS; // Register CS
while(1)
{
// EnterCriticalSection(RegCS);
I2c_Initialize( );
error |= SHT2x_SoftReset();
RETAILMSG(1,(TEXT("rn0.rest error0= %d rn"),error));
error=0;
// --- measure humidity with "Hold Master Mode (HM)" ---
error |= SHT2x_MeasureHM(TEMP, &sT);
RETAILMSG(1,(TEXT("1.TEMP messure error= %d rn"),error));
error=0;
// --- measure temperature with "Polling Mode" (no hold master) ---
// error |= SHT2x_MeasureHM(HUMIDITY, &sRH);
// RETAILMSG(1,(TEXT("2.HUMIDITY messure error= %d rn"),error));
// error=0;
// --- calculate humidity and temperature --
RETAILMSG(1,(TEXT("3.Temperature is %x ℃rn"),sT));
// RETAILMSG(1,(TEXT("4.humidity is %x'H rn"),sRH));
fTempeValue = SHT2x_CalcTemperatureC(sT);
// fHumiValue = SHT2x_CalcRH(sRH);
RETAILMSG(1,(TEXT("5.Temperature is %.2f℃ rn"),fTempeValue));
// RETAILMSG(1,(TEXT("6.humidity is %.2f 'H rn"),fHumiValue));
SHT_Data[0] = fTempeValue ;
// SHT_Data[1] = fHumiValue ;
// LeaveCriticalSection(RegCS);
Sleep(1);
}
return 0;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
BOOL SHT_IOControl(DWORD hOpenContext,
DWORD dwCode,
PBYTE pBufIn,
DWORD dwLenIn,
PBYTE pBufOut,
DWORD dwLenOut,
PDWORD pdwActualOut)
{
//SHT2x_Option(tmp);
memcpy(pBufOut,SHT_Data,2);//output
dwLenOut = 2;//
RETAILMSG(0,(TEXT("SHT21: Ioctl code = 0x%xrn"), dwCode));
return TRUE;
}