2440+IIC--发从机地址失败

yu_baobei 2010-11-13 03:46:32
我用的是友善之臂的开发板(2440),自己做了个ZLG7290控制实验板子,功能时键盘扫描和合数码管显示控制。
2440的BSP包不带IIC驱动,我从2410BSP包移植过来的,就修改了一下逻辑中断号。
现在的问题是打开驱动时发从机地址老失败。不知道是什么原因 。下边我附上硬件原理图和驱动代码。
...全文
538 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
yu_baobei 2010-11-16
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 rushonin 的回复:]
用示波器量下波形吧,看看波形如何。
另外要确认在发送iic请求前,硬件是否需要初始化。
[/Quote]
初始化了啊 现在怀疑是硬件的错误
函数名称: I2C_InitHareware
描 述: 初始化I2C主控器寄存器
输入参数: 无
输出参数: 无
返 回: 无
********************************************************************************************/
PRIVATE void I2C_InitHareware(void)
{
// 设置相关引脚为I2C引脚
s2440IOP->rGPECON = (s2440IOP->rGPECON & 0x0FFFFFFF) | 0xA0000000;

// 禁止内部上拉电阻
s2440IOP->rGPEUP = s2440IOP->rGPEUP | 0xC000;

yu_baobei 2010-11-16
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 yu_baobei 的回复:]
0X70 没错吧
驱动应该没错误 因为我用它做E2PROM是可以的
[/Quote]
资料上都这样说的 我QQ181173354 可以加吗 谢谢
rushonin 2010-11-16
  • 打赏
  • 举报
回复
用示波器量下波形吧,看看波形如何。
另外要确认在发送iic请求前,硬件是否需要初始化。
loongembedded 2010-11-16
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 yu_baobei 的回复:]
0X70 没错吧
驱动应该没错误 因为我用它做E2PROM是可以的
[/Quote]
楼主知道怎么确定你的IIC从设备ZLG7290的从地址吧,如果你确定没有错,那还是多增加一些调试信息来找出ERROR: IIC_Write: send slave address fail的原因。
yu_baobei 2010-11-15
  • 打赏
  • 举报
回复
0X70 没错吧
驱动应该没错误 因为我用它做E2PROM是可以的
loongembedded 2010-11-15
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 yu_baobei 的回复:]
加了啊
超级终端的显示是
ERROR: IIC_Write: send slave address fail!!!
没别的啊
[/Quote]
那楼主要确认你的IIC从设备ZLG7290的从地址设置是否正常了。
yu_baobei 2010-11-14
  • 打赏
  • 举报
回复
加了啊
超级终端的显示是
ERROR: IIC_Write: send slave address fail!!!
没别的啊
loongembedded 2010-11-14
  • 打赏
  • 举报
回复
[Quote=引用楼主 yu_baobei 的回复:]
我用的是友善之臂的开发板(2440),自己做了个ZLG7290控制实验板子,功能时键盘扫描和合数码管显示控制。
2440的BSP包不带IIC驱动,我从2410BSP包移植过来的,就修改了一下逻辑中断号。
现在的问题是打开驱动时发从机地址老失败。不知道是什么原因 。下边我附上硬件原理图和驱动代码。
[/Quote]
我觉得楼主还是通过多添加一些串口输出信息来定位为什么发送从地址老是失败吧。
yu_baobei 2010-11-13
  • 打赏
  • 举报
回复
/*******************************************************************************************
函数名称: IIC_Init
描 述: 驱动程序初始化函数
输入参数: DWORD dwContext: 设备管理器传递给本驱动的参数, 通常为流接口驱动在注册表内的位置
输出参数: 无
返 回: 驱动程序句柄
*******************************************************************************************/
PUBLIC DWORD
IIC_Init(DWORD dwContext)
{
DWORD IDThread;

// 取得 GPIO 及 IIC 相关寄存器的虚拟地址空间
I2C_InitializeAddresses();

// 使能 IIC 引脚为中断引脚, 并初始化相关寄存器
I2C_InitHareware();

// 从 OAL 请求一个 SYSINTR 值
/* if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &g_I2CIrq, sizeof(UINT32), &g_I2CSysIntr, sizeof(UINT32), NULL))
{
RETAILMSG(1, (TEXT("ERROR: I2C Bus: Failed to request sysintr value for I2C Bus interrupt.\r\n")));
return(0);
}*/
// RETAILMSG(1,(TEXT("INFO: I2C Bus: Mapped Irq 0x%x to SysIntr 0x%x.\r\n"), g_I2CIrq, g_I2CSysIntr));

gI2CIntrThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) I2C_IntrThread, 0, 0, &IDThread);
if (gI2CIntrThread == 0)
{
RETAILMSG(1, (TEXT("::: CreateThread() Fail\r\n")));
return 0;
}
SetThreadPriority(gI2CIntrThread, THREAD_PRIORITY_ABOVE_NORMAL);

gI2CEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

return (DWORD)gI2CIntrThread;
}


/*******************************************************************************************
函数名称: DllEntry
描 述: 驱动程序动态库入口
输入参数:
输出参数:
返 回:
*******************************************************************************************/
PUBLIC BOOL WINAPI
DllEntry(HANDLE hInstDll, DWORD dwReason, LPVOID lpvReserved)
{
switch ( dwReason )
{
case DLL_PROCESS_ATTACH:
RETAILMSG(1, (TEXT("IIC: DLL_PROCESS_ATTACH\r\n")));
DisableThreadLibraryCalls((HMODULE) hInstDll);
break;

case DLL_PROCESS_DETACH:
RETAILMSG(1, (TEXT("IIC: DLL_PROCESS_DETACH\r\n")));
break;
}

return (TRUE);
}


/*******************************************************************************************
函数名称: IIC_Close
描 述: 驱动程序关闭函数
输入参数: DWORD Handle:驱动程序句柄
输出参数: 无
返 回: FALSE: 失败 TRUE: 成功
*******************************************************************************************/
BOOL IIC_Close(DWORD Handle)
{
g_OpenCount = 0;

return TRUE;
} // IIC_Close


/*******************************************************************************************
函数名称: IIC_Deinit
描 述: 驱动程序卸载函数
输入参数: DWORD dwContext: 驱动程序句柄
输出参数: 无
返 回: FALSE: 失败 TRUE: 成功
*******************************************************************************************/
BOOL IIC_Deinit(DWORD dwContext)
{
RETAILMSG(1, (TEXT(":::IIC: IIC Driver deinit.\r\n")));

// 通知中断服务线程退出
g_bKillIST = TRUE;
PulseEvent(gI2CIntrEvent);
Sleep(200); /* 等待.... */

// 释放中断资源
InterruptDone(SYSINTR_IIC);
InterruptDisable(SYSINTR_IIC);
//KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &g_I2CSysIntr, sizeof(UINT32), NULL, 0, NULL);

// 恢复 I2C 引脚为输入引脚
I2C_ConfigPinDefault();

/* 释放申请的虚拟内存 */
if (s2440IOP)
VirtualFree((PVOID)s2440IOP, 0, MEM_RELEASE);

if (s2440IIC)
VirtualFree((PVOID)s2440IIC, 0, MEM_RELEASE);

// 关闭 I2C 事件句柄
CloseHandle(gI2CEvent);
g_OpenCount = 0;

return TRUE;
} // IIC_Deinit

yu_baobei 2010-11-13
  • 打赏
  • 举报
回复
*******************************************************************************************
函数名称: I2C_GetSpeed
描 述: 取得 I2C 的传输速度
输入参数: 无
输出参数: 无
返 回: I2C 总线的传输速度, 单位为 Hz
********************************************************************************************/
PRIVATE DWORD I2C_GetSpeed(void)
{
PROCESSOR_INFO procInfo;
DWORD dwBytesReturned;
DWORD pclk, i2cspeed;

/* get the information of the device */
if (!KernelIoControl(IOCTL_PROCESSOR_INFORMATION, NULL, 0, &procInfo, sizeof(PROCESSOR_INFO), &dwBytesReturned))
{
pclk = DEFAULT_S3C2410X_PCLK;
RETAILMSG(TRUE, (TEXT("WARNING: I2C_GetSpeed:: failed to obtain processor frequency - using default value (%d).\r\n"), pclk));
}
else
{
pclk = procInfo.dwClockSpeed;
}

/* calculate the clock of IIC transmit speed */
i2cspeed = pclk / 512 / ((s2440IIC->rIICCON & 0x0F) + 1);

return i2cspeed;
}


/*******************************************************************************************
函数名称: StartI2C
描 述: 启动总线,发送从机地址,并发送从机地址
输入参数: BYTE sla: 从机地址
输出参数: 无
返 回: 无
********************************************************************************************/
void StartI2C(BYTE sla)
{
s2440IIC->rIICDS = sla; // 设置从机地址

if(sla & 0x01)
{
s2440IIC->rIICSTAT = (2 << 6) | (1 << 5) | (1 << 4); // 主接收模式,发送使能,启动总线
IICCON_DACK(s2440IIC->rIICCON); // 若是重启总线, 则需要有此操作
}
else
{
s2440IIC->rIICSTAT = (3 << 6) | (1 << 5) | (1 << 4); // 主发送模式,发送使能,启动总线
}

}


/*******************************************************************************************
函数名称: StopI2C
描 述: 结束总线
输入参数: BYTE send: I2C当前模模式.主发送模式时为1,否则为0(主接收模式)
输出参数: 无
返 回: 无
********************************************************************************************/
void StopI2C(BYTE send)
{
if(send)
{
s2440IIC->rIICSTAT = (3 << 6) | (0 << 5) | (1 << 4); // 发送结束信号
}
else
{
s2440IIC->rIICSTAT = (2 << 6) | (0 << 5) | (1 << 4); // 发送结束信号
}

IICCON_DACK(s2440IIC->rIICCON);

Sleep(1); // 等待结束信号产生完毕
}


/*******************************************************************************************
函数名称: SendByteI2C
描 述: 发送一个字节的数据
输入参数: BYTE data: 要发送的字节
输出参数: 无
返 回: 无
********************************************************************************************/
void IIC_SendByte(BYTE data)
{
// 将数据写入I2C数据寄存器
s2440IIC->rIICDS = data;

// 清除中断标志,允许发送数据操作
IICCON_DACK(s2440IIC->rIICCON);
}


/*******************************************************************************************
函数名称: IIC_StartRecByteA
描 述: 开始接收 IIC 总线上的数据, 接收该数据时需要发送一个应答
输入参数: 无
输出参数: 无
返 回: 无
********************************************************************************************/
void IIC_StartRecByteA(void)
{
IICCON_DACK(s2440IIC->rIICCON);
}


/*******************************************************************************************
函数名称: IIC_StartRecByteNA
描 述: 开始接收 IIC 总线上的数据, 接收该数据时,不需要发送一个应答
输入参数: 无
输出参数: 无
返 回: 无
********************************************************************************************/
void IIC_StartRecByteNA(void)
{
IICCON_DNACK(s2440IIC->rIICCON);
}


/*******************************************************************************************
函数名称: IIC_RecByte
描 述: 从 IIC 总线上接收一个字节
输入参数: 无
输出参数: 无
返 回: 无
********************************************************************************************/
BYTE IIC_RecByte(void)
{
return (s2440IIC->rIICDS);
}


/*******************************************************************************************
函数名称: I2C_IntrThread
描 述: I2C 中断服务线程
输入参数: PVOID pArg: 线程输入参数
输出参数: 无
返 回: 1 或 0
********************************************************************************************/
DWORD I2C_IntrThread(PVOID pArg)
{
DWORD ret;

// 创建I2C中断中断事件
gI2CIntrEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

// 初始化 I2C 中断: 注册中断事件, 允许 I2C 中断
if (!(InterruptInitialize(SYSINTR_IIC, gI2CIntrEvent, 0, 0)))
{
CloseHandle(gI2CIntrEvent);
RETAILMSG(1, (TEXT("ERROR: I2C Bus: Interrupt initialize failed.\r\n")));
return 0;
}

// IIC 中断线程开始运行
while (1)
{
ret = WaitForSingleObject(gI2CIntrEvent, INFINITE);
if ((ret != WAIT_OBJECT_0) || (g_bKillIST == TRUE)) /* 驱动卸载或错误发生 */
{
CloseHandle(gI2CIntrEvent);
RETAILMSG(1, (TEXT("INFO: I2C Bus Driver DeInit or Error Occur. \r\n")));
return 0; /* 线程退出 */
}

switch(I2cStatus)
{
// Start IIC Status
case I2C_STATUS_SETADDR:
if((s2440IIC->rIICSTAT & 0x09) == 0) // 发送地址成功
{
SetEvent(gI2CEvent);
IICError = I2C_ERROR_NO_ERR;
}
else
{
if (I2cCurSla & I2C_READ)
s2440IIC->rIICSTAT = (2 << 6) | (0<<5) | (1<<4); // 读终止
else
s2440IIC->rIICSTAT = (3 << 6) | (0<<5) | (1<<4); // 写终止

IICCON_DACK(s2440IIC->rIICCON);
Sleep(1); // 等待结束信号产生完毕

SetEvent(gI2CEvent);
IICError = I2C_ERROR_SETADDR;
}
break;

// Send Bytes Status
case I2C_STATUS_SEND:
if((s2440IIC->rIICSTAT & 0x09) == 0) // 数据成功发送
{
IICError = I2C_ERROR_NO_ERR;
SetEvent(gI2CEvent);
}
else
{
s2440IIC->rIICSTAT = (3 << 6) | (0 << 5) | (1 << 4);

IICCON_DACK(s2440IIC->rIICCON);
Sleep(1); // 等待结束信号产生完毕

IICError = I2C_ERROR_SEND;
SetEvent(gI2CEvent);
}
break;

// Receive Bytes
case I2C_STATUS_RECEIVE:
if((s2440IIC->rIICSTAT & 0x08) == 0)
{

IICError = I2C_ERROR_NO_ERR;
SetEvent(gI2CEvent);
}
else
{
// 发送结束信号
s2440IIC->rIICSTAT = (2 << 6) | (0 << 5) | (1 << 4);
IICCON_DACK(s2440IIC->rIICCON);
Sleep(1); // 等待结束信号产生完毕

IICError = I2C_ERROR_RECEIVE;
SetEvent(gI2CEvent);
}
break;

default:
break;
}

InterruptDone(SYSINTR_IIC);
}

}
yu_baobei 2010-11-13
  • 打赏
  • 举报
回复
不知道怎么发图片 ,先发驱动代码吧
#include <windows.h>
//#include <ceddk.h>
#include <nkintr.h>
#include <oalintr.h>
#include <pm.h>
#include "pmplatform.h"
#include "Pkfuncs.h"
#include "s2440.h"


#include "I2C.h"

#define PRIVATE static
#define PUBLIC


/* 中断事件 */
PRIVATE HANDLE gI2CIntrEvent;

/* 是否退出中断服务线程 */
PRIVATE UINT32 g_bKillIST = FALSE;

/* 读I2C事件*/
PRIVATE HANDLE gI2CEvent;

/* 中断处理线程 */
PRIVATE HANDLE gI2CIntrThread;


/* I2C 的物理中断号及逻辑中断号 */
//UINT32 g_I2CIrq = IRQ_IIC;
//UINT32 g_I2CSysIntr = SYSINTR_UNDEFINED;


/* GPIO 寄存器对应的虚拟地址 */
//PRIVATE volatile S3C2410X_IOPORT_REG * v_pIOPregs;
//PRIVATE volatile S3C2410X_IICBUS_REG * v_pIICPregs;

volatile IOPreg *s2440IOP = (IOPreg *)IOP_BASE;
volatile IICreg *s2440IIC = (IICreg *)IIC_BASE;



// I2C总线设置宏定义: 使能 ACK 位, 使能发送/接收中断, IICCLK = PCLK/512 = 132161
#define IICCON_DEFAULT ((1 << 7) | (1 << 6) | (1 << 5) | (0 << 0))

#define IICCON_DACK(rIICCON) rIICCON = rIICCON & (~(1 << 4)) | (1 << 7); /* 使能 ACK 位 */
#define IICCON_DNACK(rIICCON) rIICCON &= ~((1 << 4) | (1 << 7)); /* 禁止 ACK 位 */


#define IICCON_CLEAR_PENDING(IICCON) rIICCON &= ~(1 << 4); /* 使能 ACK 位 */

/* */
#define I2C_READ 0x01
#define I2C_WRITE 0x00

/* 定义 I2C 总线的各种状态, 中断服务线程根据该状态运行 */
#define I2C_STATUS_SETADDR 0x01 /* 设置地址状态 */
#define I2C_STATUS_RECEIVE 0x02 /* 接收状态 */
#define I2C_STATUS_SEND 0x03 /* 发送状态 */


#define I2C_ERROR_NO_ERR 0x0
#define I2C_ERROR_SETADDR 0x1
#define I2C_ERROR_RECEIVE 0x2
#define I2C_ERROR_SEND 0x3

#define I2C_RW_TIMEOUT 2000


PRIVATE BYTE volatile I2cStatus;
PRIVATE BYTE volatile I2cCurSla; /* I2C从机,当前地址 */
PRIVATE BYTE volatile I2cSla = 0xA0; /* I2C从机地址 */
PRIVATE BYTE IICError = 0;

PRIVATE DWORD g_OpenCount = 0;

/*******************************************************************************************
函数名称: I2C_InitHareware
描 述: 初始化I2C主控器寄存器
输入参数: 无
输出参数: 无
返 回: 无
********************************************************************************************/
PRIVATE void I2C_InitHareware(void)
{
// 设置相关引脚为I2C引脚
s2440IOP->rGPECON = (s2440IOP->rGPECON & 0x0FFFFFFF) | 0xA0000000;

// 禁止内部上拉电阻
s2440IOP->rGPEUP = s2440IOP->rGPEUP | 0xC000;

// 设置I2C控制寄存器 (使能ACK位时才能接收从机的应答位)
s2440IIC->rIICCON = IICCON_DEFAULT;

// 设置I2C为主机模式
s2440IIC->rIICSTAT = (3 << 6) | (1 << 4);

// 从机地址 (作主机时没有用)
s2440IIC->rIICADD = 0x10;
}

/*******************************************************************************************
函数名称: I2C_ConfigPinDefault
描 述: 配置I2C引脚恢复为输入引脚
输入参数: 无
输出参数: 无
返 回: 无
********************************************************************************************/
PRIVATE VOID I2C_ConfigPinDefault(VOID)
{
// Set GPE14, GPE15 is Input
s2440IOP->rGPFCON &= ~((0x3 << 28) + (0x3 << 30));
}


/*******************************************************************************************
函数名称: I2C_InitializeAddresses
描 述: 取得I2C主控器相关寄存器的虚拟地址
输入参数: 无
输出参数: 无
返 回: > 0 分配到的虚拟地址; FALSE: 失败
********************************************************************************************/
PRIVATE BOOL I2C_InitializeAddresses(void)
{
BOOL RetValue = TRUE;

RETAILMSG(1, (TEXT(">>> IIC_initalization address..set..\r\n")));

// IO Register Allocation
// GPIO Virtual alloc
s2440IOP = (volatile IOPreg *) VirtualAlloc(0,sizeof(IOPreg),MEM_RESERVE, PAGE_NOACCESS);
if(s2440IOP == NULL) {
RETAILMSG(1,(TEXT("For s2440IOP: VirtualAlloc failed!\r\n")));
}
else {
if(!VirtualCopy((PVOID)s2440IOP,(PVOID)(IOP_BASE),sizeof(IOPreg),PAGE_READWRITE | PAGE_NOCACHE )) {
RETAILMSG(1,(TEXT("For s2440IOP: VirtualCopy failed!\r\n")));
}
}


// iic Virtual alloc
s2440IIC = (volatile IICreg *) VirtualAlloc(0,sizeof(IICreg),MEM_RESERVE, PAGE_NOACCESS);
if(s2440IIC == NULL) {
RETAILMSG(1,(TEXT("For s2440IIC: VirtualAlloc failed!\r\n")));
}
else {
if(!VirtualCopy((PVOID)s2440IIC,(PVOID)(IIC_BASE),sizeof(IICreg),PAGE_READWRITE | PAGE_NOCACHE )) {
RETAILMSG(1,(TEXT("For s2440IIC: VirtualCopy failed!\r\n")));
}
}

}


#define DEFAULT_S3C2410X_PCLK (203000000 / 4)

/

19,524

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 嵌入开发(WinCE)
社区管理员
  • 嵌入开发(WinCE)社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧