树莓派4B-模拟I2C读取CH452矩阵按键
wiringPi 包含了一个 I2C 库,来让您能够更轻松的使用树莓派的板上 I2C 接口。I2C常用方法如下所示:
int wiringPiI2CSetup(int devId);
该函数使用指定设备标示号来初始化 I2C 系统。参数 devId 是 I2C设备地址
回值是I2C设备的文件描述符.如果返回-1则表示获取I2C设备失败
int wiringPiI2CRead (int fd) ;直接读取数据(针对无需发送寄存器地址的I2C设备),fd是wiringPiI2CSetup函数的返回值,返回值是读到的数据
int wiringPiI2CWrite (int fd, int data) ;直接写数据(针对无需发送寄存器地址的I2C设备),fd同上,data是写入的数据
int wiringPiI2CWriteReg8 (int fd, int reg, int data) ;写数据到8位寄存器,fd同上,reg寄存器地址,data要写入的数据
int wiringPiI2CWriteReg16 (int fd, int reg, int data) ;写数据到16位寄存器,fd同上,reg寄存器地址,data要写入的数据
int wiringPiI2CReadReg8 (int fd, int reg) ;从寄存器读取8位数据,fd同上,reg寄存器地址,返回值读取到的数据
int wiringPiI2CReadReg16 (int fd, int reg) ;从寄存器读取16位数据,fd同上,reg寄存器地址,返回值读取到的数据
由于CH452的I2C不是标准I2C格式,所以只能用模拟实现:
代码如下所示:
#include<stdio.h>
#include <cstring>
#include<wiringPi.h>
typedef unsigned char u8;
typedef unsigned short u16;
#define BTN_INTERRUPT 0 // 按钮中断
#define PIN_SDA 8
#define PIN_SCL 9
#define PIN_RST 7
#define CH452_SCL_SET {digitalWrite(PIN_SCL, HIGH);}
#define CH452_SCL_CLR {digitalWrite(PIN_SCL, LOW);}
#define CH452_SDA_SET {digitalWrite(PIN_SDA, HIGH);}
#define CH452_SDA_CLR {digitalWrite(PIN_SDA, LOW);}
#define CH452_SDA_IN (digitalRead(PIN_SDA))
#define CH452_SDA_D_OUT {pinMode(PIN_SDA, OUTPUT);}
#define CH452_SDA_D_IN {pinMode(PIN_SDA, INPUT);}
// 2线接口CH452
#define CH452_I2C_ADDR0 0x40 // CH452 ADDR=0
#define CH452_I2C_ADDR1 0x60 // CH452 ADDR=1
#define CH452_I2C_MASK 0x3E // CH452 掩码
#define CH452_GET_KEY 0x0700 // 读KEY命令
bool keys[80];
void CH452_I2c_Start(void)
{
CH452_SDA_D_OUT;
CH452_SDA_SET;
CH452_SCL_SET;
CH452_SDA_CLR;
CH452_SCL_CLR;
}
void CH452_I2c_Stop(void)
{
CH452_SDA_D_OUT; // 设置SDA为输出方向
CH452_SDA_CLR;
CH452_SCL_SET;
CH452_SDA_SET; // 发送结束信号
CH452_SDA_D_IN; //设置SDA为输RU方向
}
// 读一个数据
u8 CH452_I2c_RdByte(void)
{
u8 dat,i;
CH452_SDA_SET;
CH452_SDA_D_IN; // 设置SDA为输入方向
dat=0;
for(i=0;i!=8;i++)
{
CH452_SCL_SET;
delayMicroseconds(3);
dat<<=1;
if(CH452_SDA_IN) dat++; // 读出一位
CH452_SCL_CLR;
delayMicroseconds(1);
}
CH452_SDA_SET;
delayMicroseconds(1);
CH452_SCL_SET; // 发送应答
delayMicroseconds(2);
CH452_SCL_CLR;
delayMicroseconds(1);;
return(dat);
}
// 写一个字节
void CH452_I2c_WrByte(u8 dat)
{
u8 i;
CH452_SDA_D_OUT; // 输出
for(i=0;i!=8;i++)
{
if(dat&0x80) {CH452_SDA_SET;}
else {CH452_SDA_CLR;}
delayMicroseconds(1);;
CH452_SCL_SET;
dat<<=1;
delayMicroseconds(2);
CH452_SCL_CLR;
delayMicroseconds(1);;
}
CH452_SDA_D_IN; /*SDA输入方向 */
CH452_SDA_SET;
delayMicroseconds(1);
CH452_SCL_SET; // 等待应答
delayMicroseconds(2);
CH452_SCL_CLR;
delayMicroseconds(1);
}
void CH452_Write(unsigned short cmd) // 写命令
{
CH452_I2c_Start();
CH452_I2c_WrByte((u8)(cmd>>7)&CH452_I2C_MASK|CH452_I2C_ADDR1); // ADDR=1
CH452_I2c_WrByte((u8)cmd);
CH452_I2c_Stop();
}
u8 CH452_ReadKey(void)
{
u8 keycode;
CH452_I2c_Start();
CH452_I2c_WrByte((u8)(CH452_GET_KEY>>7)&CH452_I2C_MASK|0x01|CH452_I2C_ADDR1);
keycode=CH452_I2c_RdByte();
CH452_I2c_Stop();
return(keycode);
}
void irqHandler(void) {
u8 key = CH452_ReadKey() - 0X40;
keys[key] = !keys[key];
printf("INTERRUPT key%d = %d\n",key,keys[key]);
}
int initI2c()
{
//初始化所用到的IO引脚
pinMode(BTN_INTERRUPT, INPUT);
// INT_EDGE_FALLING:下降沿
// INT_EDGE_RISING:上升沿
// INT_EDGE_BOTH: 可上升沿也可以下降沿
// INT_EDGE_SETUP:保持原有的GPIO初始方式
int wiringPiI2CSetup(int devId);
wiringPiISR(BTN_INTERRUPT, INT_EDGE_FALLING, &irqHandler);
pinMode(PIN_SDA, OUTPUT);
pinMode(PIN_SCL, OUTPUT);
pinMode(PIN_RST, OUTPUT);
digitalWrite(PIN_RST, HIGH);
digitalWrite(PIN_RST, LOW);
return 0;
}
int main()
{
u8 data[10];
u8 i=0;
u8 beginData = 0;
//初始化wiringPI的库函数
if(wiringPiSetup()<0) {
printf("init wiringPi error\n");
}
initI2c(); //spi的初始化
CH452_Write(0X0403);
while(1) {
delay(100);
}
return 0;
}
效果如下所示:
人间有真情,人间有真爱。