调试HC18M003的IIC主机通讯模式程序,已经花了一天半的时间,依旧没有调通。在SDA输出端始终看不到有效的数据波形,反而是一直维持在高电平状态。调整心态,准备从头再搞一遍,为了能记录完整的操作过程,找到问题点,准备花点时间做笔记。没做一些处理,就记下来。
首先第一步,准备按照以下方式做测试程序。使能IIC外设,但不发送任何东西。检测SCL和SDA总线是否有变化,以及是否会发生IIC中断。虽然不发送数据,但仍然连接从机。从机使用PCF8574T,它的P7 - P0管脚上接上有上拉驱动的LED作为指示。如果IIC通讯成功,数据体现到P7 - P0管脚上,管脚上是低电平的,会点亮LED。同时,使用PC5作为IIC中断的指示管脚,在IIC中断处理中翻转这个管脚。
程序如下:
#include"holychip_define.h" #define DEVICEADD 0x4E //IIC器件地址 测试IIC LCD1602 //#define DEVICEADD 0xAE //IIC器件地址 unsigned char guc_IICSendData = 0; //IIC主机发送数据 unsigned char guc_IICReceiveData = 0; //IIC主机接收数据 unsigned char guc_IICErrFlag = 0; //IIC错误标志位 unsigned char gbt_IICSendReceiveFlag = 0; //0:发送模式 1:接收模式 unsigned char gbt_IICReveivingFlag = 0; //标志位为1时,认为正在接收数据 unsigned char gbt_IICBusyingFlag = 0; //忙信号,忙时禁止发送和接收 unsigned char fuc_IICStep = 0; void IICSendReceiveStart(unsigned char fuc_IICSendReveiveFlag,unsigned char fuc_IICSendData); //IIC主机模式下发送或接收数据 /*************************************************************************************** * @说明 中断服务函数 * @参数 无 * @返回值 无 * @注 依据IIC状态码在中断中实现收发 ***************************************************************************************/ void interrupt IIC_Isr(void) { //==============主机发送模式==========================================================// if(IICIF) { // IIC中断,加上指示 PORTA0 = ~PORTA0; // if(!gbt_IICSendReceiveFlag) { // //主机发送模式 // switch (fuc_IICStep) { // case 0x00: //第一步:发送器件地址 // if(IICSTA == 0x08) { // IICCON &=~ 0x20; // STA=0,禁止继续发START信号 // //IICDAT = 0xAE; // IICDAT = DEVICEADD; // fuc_IICStep = 0x01; // break; // } else { // //未正常接收ACK信号 // fuc_IICStep = 0xFF; // } // // case 0x01: //第二步:发送数据 // if(IICSTA == 0x18) { // IICDAT = guc_IICSendData; // fuc_IICStep = 0x02; // break; // } else { // //未正常接收ACK信号 // fuc_IICStep = 0xFF; // } // // case 0x02: //第二步:从机接收数据,发送完成 // if(IICSTA == 0x28) { // IICCON |= 0x10; // fuc_IICStep = 0x00; // gbt_IICBusyingFlag = 0; // break; // } else { // //未正常接收ACK信号 // fuc_IICStep = 0xFF; // } // // case 0xFF: //未正常接收ACK信号 // fuc_IICStep = 0; // guc_IICErrFlag = 1; // gbt_IICBusyingFlag = 0; // break; // default:break; // } // } IICIF = 0; //清除中断标志位 } } /*************************************************************************************** * @说明 IIC主机模式下发送或接收数据 * @参数 fuc_IICSendReveiveFlag:IIC发送标志位 0:发送模式 1:接收模式 fuc_IICSendData: IIC发送数据 * @返回值 无 * @注 若fuc_IICSendReveiveFlag=1时形参fuc_IICSendData无效可任意传入 ***************************************************************************************/ void IICSendReceiveStart(unsigned char fuc_IICSendReveiveFlag,unsigned char fuc_IICSendData) { if(!fuc_IICSendReveiveFlag) { guc_IICSendData = fuc_IICSendData; //发送数据 gbt_IICBusyingFlag = 1; //IIC正在发送数据标志位 gbt_IICSendReceiveFlag = 0; //当前为主机发送 } else { gbt_IICBusyingFlag = 1; //IIC正在发送数据标志位 gbt_IICSendReceiveFlag = 1; //当前为主机接收 } IICIF = 0; IICCON |= 0x20; // 产生开始信号 } /*************************************************************************************** * @实现效果 IIC主机发送与接收 ***************************************************************************************/ void main() { unsigned int i=0; unsigned int j=0; /************************************系统初始化****************************************/ OSCCON = 0x04; //Fosc=32M Fcpu=4M(Fosc4分频 2T) /************************************IO初始化*****************************************/ ANSELC = 0xFF; //PC口所有管脚都设为数字形式 //TRISD = 0x04; //SCL映射PC2 SDA映射PC0时IO配置 TRISC = 0x05; //PC0、PC2均设为输出模式, PC0-SDA,PC2-SCL IICMAP = 0x11; //SCL映射PC2 SDA映射PC0 映射后默认将IIC_SDA口设为开漏带上拉输出 ANSELA = 0x01; //PA0设为数字形式 TRISA = 0x01; //PA0为输出口-IIC中断指示 /************************************IIC初始化*****************************************/ IICCON = 0x40; //启动IIC模块 IICIE = 1; //允许IIC中断 PEIE = 1; //允许未屏蔽中断 GIE = 1; //允许总中断 PORTA0 = 1; IICIF = 0; // IICCON |= 0x20; // 产生开始信号 while(1) { // IICSendReceiveStart(0,0xA5); //0,AA:IIC开始发送AA // while(gbt_IICBusyingFlag); //发送中,忙信号 // // for (i=0; i<50000; i++) { // for (j=0; j<200; j++) { // // 延迟 // } // } } }
实际测试,SCK和SDA总线上没有数据变化,IIC没发生中断。与预想的一样,没有任何问题。