mini2440下调试IIC时序问题总结与分析

发布者:delta14最新更新时间:2024-06-20 来源: elecfans关键字:mini2440  调试IIC  时序问题 手机看文章 扫描二维码
随时随地手机看文章

说明: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);

[1] [2]
关键字:mini2440  调试IIC  时序问题 引用地址:mini2440下调试IIC时序问题总结与分析

上一篇:2440GPIO口在Linux中的定义
下一篇:mini2440 ADC可调电阻驱动程序开发源代码(杂项设备驱动框架)

推荐阅读最新更新时间:2026-03-20 20:03

STM32CubeMx之硬件IIC调试基本方法
如题,最近在调试STM32的硬件IIC,从中发现了很多问题,经过网上查找资料总结和实际测试,总结出如下步骤来检测硬件IIC。 测试环境如下: STM32F407开发板; STM32Cube固件库F4 1.6.0 IIC设备 AT24C02 IIC配置如下: void MX_I2C1_Init(void) { hi2c1.Instance = I2C1; hi2c1.Init.ClockSpeed = 100000; hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; hi2c1.Init.OwnAddress1 = 0; hi2c1.Init.AddressingMode =
[单片机]
开关模式电源问题分析及其纠正措施:晶体管时序和自举电容问题
非常见问题解答第222期:开关模式电源问题分析及其纠正措施:晶体管时序和自举电容问题 问题 当输入和输出电压接近时,为什么难以获得稳定的输出电压? 回答 占空比过大或过小(尤其是在高开关频率下)可能会导致时序不符合规格要求,进而造成系统性能下降。 摘要 本文是系列文章中的第三篇,该系列文章将讨论常见的开关模式电源(SMPS)的设计问题及其纠正方案。 本文旨在解决DC-DC开关稳压器的功率级设计中面临的复杂难题,重点关注功率晶体管和自举电容 。功率晶体管具有最小和最大占空比,如果违反限值,将会导致SMPS性能下降。此外,如果忽略自举电容,晶体管将无法正常工作。 引言 在本文中,降压转换器用于演示
[电源管理]
开关模式电源<font color='red'>问题</font>分析及其纠正措施:晶体管<font color='red'>时序</font>和自举电容<font color='red'>问题</font>
89和12单片机的I2C通信时序问题
今天用ADC偶然发现了这个问题,分享给各位朋友。 89的I2CDelay: #define I2CDelay() {_nop_();_nop_();_nop_();_nop_();} 12的I2CDelay: void Delay_us(unsigned char us) { do { _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); } while (--us); } I2CDelay(5); I2C通信分为低速模式100kbit/s、快速模
[单片机]
MINI2440从SD卡更新NK及nboot(一)
买了友善 MINI2440 开发板, SuperVivi 不开源,自己的板子又没有 NOR Flash ,烧入系统带来很大的困扰,无奈之下,只能自己做烧入工具来解决。大致思路,先从 SD 卡启动 WINCE ,再用工具格式化 Flash 及分区,将 Nboot 及 NK 写入相应的块。    应用程序操作 Flash ,无非就是 Read/Write/Earse Flash , CSDN 上有一牛人写 在 WinCE 下,应用程序直接读 / 写 / 擦除 flash 设备的方法 。 下面是我的部分代码: 1 BOOL FMD_OEMIoControl(DWORD dwIoControlCode, PBYTE pInBu
[单片机]
linux-2.6.32在mini2440开发板上移植 配置USB外设
编者:因为LINUX内核对S3C2440的Host驱动的已经支持,而且支持的外设相当的丰富,所以这一部分只是进行配置就可以使用。因为配置的东西较多,没有给出详细的截图,看手册上介绍的就很明白。需要手册的请留下邮箱索取。 1 配置和测试USB 键盘、扫描器和鼠标 在内核源代码目录的终端输入:make menuconfig,依次选择如下子菜单项: Device Drivers --- HID Devices --- 按空格键选中“USB Human Interface Device (full HID) support”,这样就配置好了USB键盘和鼠标项。 提示:这里的配置选项对应的内核源代码目录是:
[单片机]
Ubuntu 8.10 下移植 madplay 到 mini2440
在 Ubuntu 8.10 下移植 madplay 到 mini2440过程中同样参考了网上的一篇帖子,由于当时未想到要把过程放到这就没有记录那篇帖子的网址,在此表示感谢! madplay移植记录: 一、PC版的madplay PC版的编译基本同mini2440手册上的一致。 二、ARM版的madplay 1、编译zlib-1.2.3 解压zlib-1.2.3.tar.gz到/opt/FriendlyARM/mini2440/madplay/src-arm/zlib-1.2.3 进入zlib-1.2.3目录 配置configure: sudo gedit configure a、把AR=${AR- ar rc }改为: AR=${
[单片机]
mini2440开发板Linux系统自动挂载U盘与SD卡失败的解决方法
对于有些U盘和SD卡,mini2440开发板自带的Linux系统不能有效的自动挂载在文件系统里面,这是因为mini2440的/etc/mdev.conf 和 /bin/hotplug.sh这两个文件写的不太完善,我经过测试,发现其中的内容需要改进,在/etc/mdev.conf文件中,只需将以下内容写至末尾即可: mmcblk 0:0 0666 =sdcard * /bin/hotplug.sh sd 0:0 0666 =udisk * /bin/hotplug.sh 在/bin/hotplug.sh文件中则需要把以下内容加在 “case $MDEV in” 的后面: sd ) DEVNAME=udisk MO
[单片机]
u-boot-2009.08在mini2440上的移植 增加I2C EEPROM功能
移植环境 1,主机环境:VMare下CentOS 5.5 ,1G内存。 2,集成开发环境:Elipse IDE 3,编译编译环境:arm-linux-gcc v4.4.3,arm-none-eabi-gcc v4.5.1。 4,开发板:mini2440,2M nor flash,128M nand flash。 5,u-boot版本:u-boot-2009.08 6,参考文章: 10.1,实现u-boot的I2C EEPROM功能 mini2440开发板上的AT24C08A芯片提供了8kbyte的非易失的EEPROM存储空间,而且是通过I2C协议进行读写的,U-boot提供了对I2C和EEPROM的操作支持。 打开/include
[单片机]
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved