用树霉pi的io模拟i2c协议读取 24c256 eeprom 24c256支持最高1Mbps
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include "gpio.h"
#define sclpin 22 // gpio pin num
#define sdapin 27
#define ID 0x50
#define I2CFREQ 1e6
#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);
void delayhalf(){ delaycycle(DT/2); }
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 writeWaitSDAh(int val) { SDA(val); delayhalf(); return waitPin(i2c.sda,val); }
int writeWaitSCL(int val) { SCL(val); delay(); return waitPin(i2c.scl,val);}
int writeWaitSCLh(int val) { SCL(val); delayhalf(); return waitPin(i2c.scl,val);}
int i2cStart()
{
writeWaitSCLh(0);
SDA(1);
writeWaitSCLh(0);
writeWaitSCLh(1);
SDA(0);
writeWaitSCLh(1);
writeWaitSCLh(0);
}
void i2cStop()
{
SDA(0);
writeWaitSCLh(0);
writeWaitSCLh(1);
SDA(1);
writeWaitSCLh(1);
}
void i2cSendBit( int bit)
{
SDA(bit);
writeWaitSCLh(0);
writeWaitSCL(1);
writeWaitSCLh(0);
}
void i2cSendAck(int bit)
{
i2cSendBit(bit);
if(!bit)
SDA(1);
}
int i2cReceiveBit()
{
writeWaitSCLh(0);
writeWaitSCL(1);
int res = readSDA();
writeWaitSCLh(0);
return res;
}
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();
i2cSendAck(0);
return data;
}
unsigned char i2cRecieveByteNA() {
unsigned char data;
data = i2cReceiveByte();
i2cSendAck(1);
return data;
}
unsigned char at24ReadCur(unsigned char id) { //read current address cnt
i2cStart();
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);
}
unsigned char at24ReadLen(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);
i2cStart();
i2cSendByteA( id << 1 | 1);
int i;
for( i = 0; i < len-1; i++){
buf[i] = i2cRecieveByteA();
}
buf[i] = i2cRecieveByteNA();
i2cStop();
}
int _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 -1;
}
i2cSendByteA( (addr>>8) & 0xff );
i2cSendByteA (addr & 0xff);
for( int i = 0; i < len-1; i++){
i2cSendByteA(buf[i]);
}
i2cStop();
delayus(5000); // write cycle time
return 0;
// usleep(5000);
}
int at24WriteLen(unsigned char id, int addr,char* buf, int len)
{
while(len > 64) {
_at24WriteLen(id,addr,buf,64);
len -= 64;
buf += 64;
}
_at24WriteLen(id,addr,buf,64);
}
int main()
{
gpioSetup();
i2cSetup(sclpin, sdapin);
int buflen = 10;
char* buf = malloc(buflen);
memset(buf,0,buflen);
printf("readaddr test \n");
for(int i = 0; i < buflen ; i++){
printf(" %02x ",at24ReadAddr(ID,i));
}
printf("\n");
printf("readcur test \n");
for(int i = 0; i < buflen ; i++)
printf(" %02x ",i,at24ReadCur(ID));
printf("\n");
printf("write 33K and readback test \n");
int start = 0x00;
buflen = 33*1024; //33K
buf= realloc(buf,buflen);
memset(buf,0,buflen);
uint16_t* uptr = (uint16_t*)buf;
for( int i = 0; i < buflen/2; i++)
uptr[i] = i*2;
at24WriteLen( ID, start, buf, buflen);
memset(buf,0,buflen);
at24ReadLen( ID, start, buf,buflen);
for( int i = 0; i < buflen/2; i+=64){
printf(" %5d ",uptr[i]);
if(((i>>6)&0xf) == 0xf)
printf("\n");
}
printf("\n");
free(buf);
i2cRelease();
gpioRelease();
}
用的上一篇发的简易库,重发下
gpio.h
#define BCM2835_PERI_BASE 0x20000000
#define GPIO_BASE (BCM2835_PERI_BASE + 0x200000)
#define CPUFREQ 7e8
enum 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 4096
int 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;
}