众所周知,I2C主模式的模拟程序比较好写,但从模式要模拟出来却不容易 以下是我写的一个I2C总线的监测程序,能检测正在通讯的i2c总线上传送的数据 有点类似于从模式的I2C模拟程序,但很多地方没有完善,也没找到好的办法 有没有高手指点一下? 程序是测试代码,很乱,不好意思! #define __I2CMONITOR_DECL__
#include "global.h"
#include <avr/io.h> // include I/O definitions (port names, pin names, etc) //#include <avr/signal.h> // include "signal" names (interrupt names) #include <avr/interrupt.h> // include interrupt support #include <stdio.h> #include <util/delay.h>//<avr/delay.h> #include "uart.h"
//#define _READ_DROP_EDGE_ //如果需要下降沿读数 //默认为上升沿读数 #define SDA_PORT PORTD #define SDA_DDR DDRD #define SDA_PIN PIND #define SDA_POT PD2 #define SCL_PORT PORTD #define SCL_DDR DDRD #define SCL_PIN PIND #define SCL_POT PD3
#define RECEIVE_DATA_LENGTH 10 //传输一串数据的最大长度,如果小于最大数据长度,将导致接收错误
#define RECEIVE_DATA_ANOUNT 60 //传输数据串的个数,建议超过有次发送的串数,这样程序才有时间将数据输出出来 //注意,如果是自动输出的数据(不是按PD7键输出),头尾数据有一定错误(主要是丢失) //下降沿置数,上升沿读数
unsigned char gBitIndex=0; unsigned char gByteIndex=0; unsigned char gReceiveIndex=0; unsigned char gReceiveDat[RECEIVE_DATA_ANOUNT][RECEIVE_DATA_LENGTH]; unsigned char gStartFlag=0;//是否开始
void intSDAInit(void) //SDA { MCUCR |=(1<<ISC00); //电平有变化就中断 GICR |=(1<<INT0); }
void intSCLInit(void) //SCL { #ifdef _READ_DROP_EDGE_ MCUCR |= (1<<ISC11); //下降沿中断 #else MCUCR |= (1<<ISC10)|(1<<ISC11); //上升沿中断 #endif //enable_external_int(_BV(INT1)); //使能外部中断1 GICR |=(1<<INT1); } void i2cMonitorInit(void) { intSDAInit(); // cbi(SDA_DDR,SDA_POT); // sbi(SDA_PORT,SDA_POT); intSCLInit(); } SIGNAL(SIG_INTERRUPT1) //scl 上升沿,读取数据 { if (SDA_PIN&0x04/*(1<<SDA_POT)减少运算次数*/) { //如果是高电平,收到'1' if (!gStartFlag) { //如果没有开始 return; } gReceiveDat[gReceiveIndex][gByteIndex] |= 0x80>>gBitIndex; //putchar('1'); }else{//收到'0' if (!gStartFlag) { //如果没有开始 return; } //putchar('0'); } gBitIndex++; if ((gBitIndex>8)&&(gByteIndex<RECEIVE_DATA_LENGTH-1)) {//8bit数据和1bit的ack gBitIndex=0; gByteIndex++; } }
SIGNAL(SIG_INTERRUPT0) //sda 上电平有变化 { if (SCL_PIN&0x08/*(1<<SDA_POT)*/) {//如果SCL是高电平,说明是开始或者结束 if (SDA_PIN&0x04/*(1<<SDA_POT)减少运算次数*/) { //如果是上升沿,表示结束 gStartFlag=0;//结束 gReceiveDat[gReceiveIndex][0]=gByteIndex; }else{//下降沿,表示开始 gStartFlag=1;//开始 gBitIndex=0; gByteIndex=1; if (gReceiveIndex<RECEIVE_DATA_ANOUNT-1) {//用下一个数组存储 gReceiveIndex++; }else{ gReceiveIndex=0; } gReceiveDat[gReceiveIndex][0]=RECEIVE_DATA_LENGTH; } } } void delay_ms(unsigned int _msNumber_) { unsigned int i; for (i=0;i<_msNumber_;i++) { _delay_ms(1); } } int main(void) { cli(); i2cMonitorInit(); uartInit();
DDRD &=~(1<<PIND7); printf("uart start ok!\n");
unsigned char outIndex=0; unsigned char i; sei();
while (1) { if (outIndex!=gReceiveIndex) { if (gReceiveDat[gReceiveIndex][0]) { putchar('\n'); for (i=1;i<gReceiveDat[outIndex][0];i++) { printf("%02X\t",gReceiveDat[outIndex]); gReceiveDat[outIndex]=0; } gReceiveDat[outIndex][0]=0; }
if (outIndex<RECEIVE_DATA_ANOUNT-1) { outIndex++; }else{ outIndex=0; } }
} return 0; }
|