用树霉pi的io模拟i2c协议读取 24c256 eeprom
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>#include "gpio.h"#define I2CFREQ 1e5
#define DT CPUFREQ/I2CFREQ/2
// #define DT 1e6 / I2CFREQ / 2 // usleep
typedef struct {int sda;int scl;
}I2C;
I2C i2c;void i2cSetup(int scl, int sda)
{i2c.scl = scl;i2c.sda = sda;pinMode(scl,OUTPUT);pinMode(sda,OUTPUT);setPud(scl,PUD_UP); //上拉模式,测试不上拉也可以setPud(sda,PUD_UP);
}void i2cRelease() {pinMode(i2c.scl, INPUT);pinMode(i2c.sda, INPUT);setPud(i2c.scl,PUD_OFF);setPud(i2c.sda,PUD_OFF);
}void delay(){ delaycycle(DT); } //usleep(DT);
int waitPin(int pin, int val) {int n = 0, times = 10;while((readPin(pin) != val) && n++ < times)delay();return (n >= 10) ? -1 : 0;
}void SCL(int val) { writePin(i2c.scl, val & 1); }
void SDA(int val) { writePin(i2c.sda, val & 1); }
int readSCL() { return readPin(i2c.scl); }
int readSDA() { return readPin(i2c.sda); }
int writeWaitSDA(int val) { SDA(val); delay(); return waitPin(i2c.sda,val); }
int writeWaitSCL(int val) { SCL(val); delay(); return waitPin(i2c.scl,val);}int i2cStart()
{writeWaitSCL(0);writeWaitSCL(1);writeWaitSDA(1);writeWaitSDA(0);writeWaitSCL(0);
}void i2cStop()
{writeWaitSCL(0);writeWaitSDA(0);writeWaitSCL(1);writeWaitSDA(1);
}void i2cSendBit( int bit)
{writeWaitSCL(0);writeWaitSDA(bit);writeWaitSCL(1);
}int i2cReceiveBit()
{writeWaitSCL(0);SDA(1); // release sda SCL(0);writeWaitSCL(1);return readSDA();
}void i2cSendByte(unsigned char data)
{for(int i = 0; i < 8; i++) {i2cSendBit((data>>7) & 1);data <<= 1;}
}
int i2cSendByteA(unsigned char data) {i2cSendByte(data);return i2cReceiveBit();
}unsigned char i2cReceiveByte() {unsigned char data = 0;for(int i = 0; i < 8; i++) {data <<= 1;data |= ( i2cReceiveBit() & 1);}return data;
}
unsigned char i2cRecieveByteA() {unsigned char data;data = i2cReceiveByte();i2cSendBit(0);return data;
}unsigned char i2cRecieveByteNA() {unsigned char data;data = i2cReceiveByte();i2cSendBit(1);return data;
}unsigned char at24ReadCur(unsigned char id) { //read current address cnti2cStart();if( i2cSendByteA( id << 1 | 1) == 1) {printf("cannot access %x, check wire\n",id);return 0;}unsigned char data = i2cRecieveByteNA();i2cStop();return data;
}
unsigned char at24ReadAddr(unsigned char id, int addr)
{i2cStart();if( i2cSendByteA( id << 1 | 0) == 1) {printf("cannot access %x, check wire\n",id);return 0;}i2cSendByteA( (addr>>8) & 0xff);i2cSendByteA (addr & 0xff);return at24ReadCur(id);
}
void at24WriteLen(unsigned char id, int addr,char* buf, int len)
{i2cStart();if( i2cSendByteA( id << 1 | 0) == 1) {printf("cannot access %x, check wire\n",id);return 0;}i2cSendByteA( (addr>>8) & 0xff );i2cSendByteA (addr & 0xff);for( int i = 0; i < len-1; i++){i2cSendByteA(buf[i]);}i2cStop();delayus(5000);// usleep(5000);
}int main()
{gpioSetup();i2cSetup(22, 27);int res = 0;for(int i = 0; i < 10 ; i++)//printf("curadr %0x\n",at24ReadCur(0x50));printf("adr %x %0x\n",i,at24ReadAddr(0x50,i));printf("\n");i2cRelease()gpioRelease();
}
用的上一篇发的简易库,重发下
gpio.h
#define BCM2835_PERI_BASE 0x20000000
#define GPIO_BASE (BCM2835_PERI_BASE + 0x200000)
#define CPUFREQ 7e8enum Mode { INPUT,OUTPUT };
enum PullMode {PUD_OFF,PUD_DOWN,PUD_UP};void delaycycle(unsigned int cnt);
void delayus(unsigned int cnt) ;
int gpioSetup();
int gpioRelease();
void pinMode(int pin, int mode);
void writePin(int pin, int value);
int readPin(int pin);
void setPud(int pin, int value);
unsigned long long readAllPin();
gpio.c
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>
#include "gpio.h"#define PAGE_SIZE 4096int fd;
uint32_t* gpio;void rstccnt()
{unsigned int tmp;asm volatile ( "mrc p15, 0, %0, c15, c12, 0 \n""orr %0,%0,%1 \n""mcr p15, 0, %0, c15, c12, 0 \n":"+r" (tmp) : "r"(0x4));
}unsigned int readccnt()
{unsigned int tmp;asm volatile ("mrc p15, 0, %0, c15, c12, 1 \n":"=r" (tmp));return tmp;
}
void delaycycle(unsigned int cnt)
{unsigned int tmp;rstccnt();tmp = readccnt();while(tmp < cnt)tmp = readccnt();
}void delayus(unsigned int cnt) // cycle counter delay
{//cnt = ((CPUFREQ>>6) * cnt) >> 3 ;// avoid overflow unsigned long long ct = cnt;cnt = (CPUFREQ*ct)/1e6;unsigned int tmp;rstccnt();tmp = readccnt();while(tmp < cnt)tmp = readccnt();
}
int gpioSetup(){char* fname = "/dev/gpiomem";fd = open(fname,O_RDWR | O_SYNC | O_CLOEXEC);gpio = mmap(0,PAGE_SIZE,PROT_READ | PROT_WRITE,MAP_SHARED,fd,GPIO_BASE);
}int gpioRelease(){munmap(gpio,PAGE_SIZE);close(fd);
}
void pinMode(int pin, int mode)
{unsigned int offset = pin / 10;unsigned int shift = (pin%10)*3;*(gpio+offset) &= ~(0x7 << shift);if (mode == OUTPUT)*(gpio+offset) |= (1<< shift);
}#define SET0 7
#define CLR0 10
void writePin(int pin, int value)
{unsigned int offset = pin / 32;unsigned int shift = pin % 32;if(value == 0)*(gpio+CLR0+offset)= 1<<shift;else*(gpio+SET0+offset)= 1<<shift;}#define LEV0 13
int readPin(int pin)
{unsigned int offset = pin / 32;unsigned int shift = pin % 32;unsigned int value = *(gpio+LEV0+offset);return (value >> shift) & 1;
}
unsigned long long readAllPin()
{unsigned long long res = *(gpio+LEV0+1);
return res = (res << 32) | *(gpio+LEV0);
// unsigned long long* res1 = gpio+LEV0;
// return *res1;
}#define PUD 37
#define PUDCLK0 38
void setPud(int pin, int value)
{
// unsigned int prepud= *(gpio+PUD);
// unsigned int prepudclk = *(gpio+PUDCLK0+offset);unsigned int offset = pin / 32;unsigned shift = pin % 32;*(gpio+PUD)=value;delaycycle(150);//*(gpio+PUDCLK0+offset) = prepudclk|(1<<shift);*(gpio+PUDCLK0+offset) |= (1<<shift);delaycycle(150);*(gpio+PUD) = 0;*(gpio+PUDCLK0+offset) = 0;
}