Description: mini2440 platform, wince6.0 system, vs2005
After several months of study and pause, I finally added the IIC bus simulated by GPIO under wince and realized the transplantation of IIC. The chip of IIC is SHT21 temperature and humidity chip.
The reason why I haven't figured out IIC for so long is that I implemented it very early in ADS, but it was always wrong when I added it to the system! The oscilloscope captured and found that the timing was wrong after the chip was reset. I searched and searched but couldn't figure out what was going on! Now I'm stuck.
I'm stuck in a vicious circle and can't get out of it!
I posted online and netizens gave me a lot of tips. Thank you! Jonsenwu netizen's words reminded me! When the driver is added to the system, the system scheduling takes time, and the delay of the driver will be extended! According to his tips, I also asked him for further advice. I would like to thank him here! Adjust the priority of the driver so that it always keeps the right to use the CPU during operation. The delay function tested under ADS will not be the same under the system!
Things I learned from this transplant:
1. Knowledge about priority in wince
The following is the code: used to implement priority preemption
//dwThreadID = GetCurrentThread(); //Get thread ID
//dwThreadPri = CeGetThreadPriority(dwThreadID); //Get thread ID priority
//dwThreadQuantum = CeGetThreadQuantum(dwThreadID); //Get thread time slice parameter
//CeSetThreadPriority(dwThreadID, 0);// Set current thread priority to the highest
//CeSetThreadQuantum(dwThreadID, 0); //Set current thread time slice to 0 to keep CPU ownership
//
//.......... (function for operating i2c)
//
//CeSetThreadQuantum(dwThreadID, dwThreadQuantum); //Restore normal time slice
//CeSetThreadPriority(dwThreadID, dwThreadPri); //Restore normal priority
Note: There are two functions for setting the priority, one function can set the priority from 0 to 255 (CeSetThreadPriority()), and the other function can only set the application priority from 248 to 255 (SetThreadPriority())!!
After the IIC debugging is successful, there is another problem in passing the data to the application. First, I implemented the transfer in XXX_IOControl, but no data came out no matter how I tried. Finally, I put it in XXX_Read and it was OK. Here I have to explain the problem about memcpy. As follows:
2. Understanding of memcpy function
Let’s first look at the problematic writing:
unsigned short SHT_Data[2];//
memcpy(pBuffer, SHT_Data, 2);//output
The only data my application reads is the temperature, the humidity is a very high number! I'm sure an expert will see the problem at a glance!
This is because: the copy of the memcpy function is based on bytes. The number of copies I made above is 2, so only the temperature is normal, and the humidity is not copied at all.
The correct method is 4 bytes: memcpy(pBuffer, SHT_Data, 4); //output
3. GPIO description
Here I have to despise the friendly arm's technical service again! I originally used the default two pins of 2440 for GPIO (the default ones were connected to EEPROM and Camera!!, it would be strange if they were correct!), and finally found the free pins of SPI0 to get it done.
The code can be found at: http://www.linuxidc.com/Linux/2012-11/74419p2.htm
Using the simulated IIC timing of the IIC IO port on mini2440 to drive a peripheral chip, the ADS debugging is correct, but it does not work when added to the system. The priority of the driver is also increased, but it is still incorrect.
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);
//
// . . . . . . (This part is the function for operating 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 acknowledgment -> 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 byte
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)
Previous article:Definition of 2440GPIO port in Linux
Next article:mini2440 ADC adjustable resistor driver development source code (miscellaneous device driver framework)
Recommended ReadingLatest update time:2024-11-15 07:20
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
- Learn ARM development (4)
- Learn ARM development (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- CGD and Qorvo to jointly revolutionize motor control solutions
- CGD and Qorvo to jointly revolutionize motor control solutions
- Keysight Technologies FieldFox handheld analyzer with VDI spread spectrum module to achieve millimeter wave analysis function
- Infineon's PASCO2V15 XENSIV PAS CO2 5V Sensor Now Available at Mouser for Accurate CO2 Level Measurement
- Advanced gameplay, Harting takes your PCB board connection to a new level!
- Advanced gameplay, Harting takes your PCB board connection to a new level!
- A new chapter in Great Wall Motors R&D: solid-state battery technology leads the future
- Naxin Micro provides full-scenario GaN driver IC solutions
- Interpreting Huawei’s new solid-state battery patent, will it challenge CATL in 2030?
- Are pure electric/plug-in hybrid vehicles going crazy? A Chinese company has launched the world's first -40℃ dischargeable hybrid battery that is not afraid of cold
- Model electronics help
- TI C2000 Piccolo single chip - realize dual-axis servo motor and motor control
- ad14 always wait a moment when opening
- A novice’s question is, how to find the most suitable chip when making hardware?
- 64 details that must be paid attention to in switching power supply design
- Domestic voltage regulator device
- How does a “temperature gun” measure your temperature?
- CC2650 launchpad and msp432 launchpad
- Switching Power Supply Interest Group 19th Task
- LED power supply not working