331 lines
8.8 KiB
C++
331 lines
8.8 KiB
C++
#include <iostream>
|
||
#include <iomanip>
|
||
#include <memory>
|
||
#include <thread>
|
||
#include <chrono>
|
||
#include <functional>
|
||
#include <fcntl.h>
|
||
#include <poll.h>
|
||
#include <unistd.h>
|
||
|
||
#define I2C_SDA 43 // GPIO1_B3
|
||
#define I2C_SCL 44 // GPIO1_B4
|
||
#define I2C_INT 52
|
||
|
||
typedef unsigned char UINT8;
|
||
typedef unsigned short UINT16;
|
||
|
||
#define STATUS_SUCCESS 0
|
||
#define STATUS_FAILURE -1
|
||
|
||
#define CH455_GET_KEY 0x0700 // 获取按键,返回按键代码
|
||
#define CH455_SYSOFF 0x0400 // 关闭显示、关闭键盘
|
||
|
||
#define CH455_I2C_ADDR 0x40 // CH455的地址
|
||
#define CH455_I2C_MASK 0x3E // CH455的高字节命令掩码
|
||
|
||
#define CH455_BIT_ENABLE 0x01
|
||
// #define CH455_BIT_ENABLE 0x03 // 开启/关闭位
|
||
#define CH455_BIT_SLEEP 0x04 // 睡眠控制位
|
||
|
||
#define CH455_SYSON (CH455_SYSOFF | CH455_BIT_ENABLE)
|
||
#define CH455_SLEEPOFF CH455_SYSOFF // 关闭睡眠
|
||
#define CH455_SLEEPON (CH455_SYSOFF | CH455_BIT_SLEEP) // 开启睡眠
|
||
|
||
static unsigned char TxBuf[24] = {0};
|
||
static unsigned char RxBuf[24] = {0};
|
||
|
||
void CH455_I2c_Stop(void);
|
||
void CH455_I2C_WrByte(unsigned char IIC_Byte);
|
||
|
||
void delay_us(int i)
|
||
{
|
||
int j, k;
|
||
for (j = 0; j < i; j++)
|
||
for (k = 0; k < 10; k++)
|
||
;
|
||
}
|
||
|
||
void initGpio(int addr)
|
||
{
|
||
// printf("开始创建GPIO%d节点\n", addr);
|
||
FILE *fp = fopen("/sys/class/gpio/export", "w");
|
||
if (fp == NULL)
|
||
perror("export open filed");
|
||
else
|
||
fprintf(fp, "%d", addr);
|
||
|
||
fclose(fp);
|
||
// printf("结束创建GPIO%d节点\n", addr);
|
||
}
|
||
|
||
// 设置为gpio方向
|
||
void setGpioDirection(int addr, char *direction)
|
||
{
|
||
// printf("设置第GPIO%d为out模式\n",addr);
|
||
char path[100] = {0};
|
||
sprintf(path, "/sys/class/gpio/gpio%d/direction", addr);
|
||
FILE *fp = fopen(path, "w");
|
||
if (fp == NULL)
|
||
perror("direction open filed");
|
||
else
|
||
fprintf(fp, "%s", direction);
|
||
fclose(fp);
|
||
// printf("结束设置第GPIO%d为out模式\n",addr);
|
||
}
|
||
|
||
// 设置gpio的电平
|
||
void set_gpioValue(int addr, int value)
|
||
{
|
||
// printf("设置GPIO%d为%d\n", addr, value);
|
||
char path[64];
|
||
snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", addr);
|
||
FILE *fp = fopen(path, "w");
|
||
if (fp == NULL)
|
||
perror("direction open filed");
|
||
else
|
||
fprintf(fp, "%d", value);
|
||
fclose(fp);
|
||
// printf("结束设置GPIO%d位置为%d\n", addr, value);
|
||
}
|
||
|
||
void IOWR_OUT(int addr, int val)
|
||
{
|
||
initGpio(addr);
|
||
setGpioDirection(addr, "out");
|
||
set_gpioValue(addr, val);
|
||
}
|
||
|
||
void IOWR_IN(int addr, int val)
|
||
{
|
||
initGpio(addr);
|
||
setGpioDirection(addr, "in");
|
||
set_gpioValue(addr, val);
|
||
}
|
||
|
||
// 读gpio节点状态
|
||
int IORD(int addr)
|
||
{
|
||
char path[64];
|
||
char value_str[3];
|
||
|
||
snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", addr);
|
||
// printf("/sys/class/gpio/gpio%d/value", addr);
|
||
FILE *fp = fopen(path, "r");
|
||
|
||
// fd = open(path, O_RDONLY);
|
||
if (fp == NULL)
|
||
{
|
||
printf("Failed to open gpio value for reading!");
|
||
return -1;
|
||
}
|
||
if (fread(value_str, sizeof(char), 3, fp) < 0)
|
||
{
|
||
perror("Failed to read value!");
|
||
return -1;
|
||
}
|
||
|
||
fclose(fp);
|
||
// printf("读取GPIO状态结束\n");
|
||
return (atoi(value_str));
|
||
}
|
||
|
||
// 开始位
|
||
void CH455_I2c_Start(void)
|
||
{
|
||
IOWR_OUT(I2C_SDA, 1);
|
||
delay_us(5);
|
||
IOWR_OUT(I2C_SCL, 1);
|
||
delay_us(5);
|
||
IOWR_OUT(I2C_SDA, 0);
|
||
delay_us(5);
|
||
IOWR_OUT(I2C_SCL, 0);
|
||
delay_us(5);
|
||
}
|
||
|
||
// 结束位
|
||
void CH455_I2c_Stop(void)
|
||
{
|
||
IOWR_OUT(I2C_SCL, 0);
|
||
delay_us(5);
|
||
IOWR_OUT(I2C_SDA, 0);
|
||
delay_us(5);
|
||
IOWR_OUT(I2C_SCL, 1);
|
||
delay_us(5);
|
||
IOWR_OUT(I2C_SDA, 1);
|
||
delay_us(5);
|
||
}
|
||
|
||
// 主控端写入一个字节到从机
|
||
void CH455_I2C_WrByte(unsigned char IIC_Byte)
|
||
{
|
||
unsigned char i;
|
||
for (i = 0; i < 8; i++)
|
||
{
|
||
// IOWR(I2C_SCL, 0); //钳住I2C总线,准备发送数据
|
||
if (IIC_Byte & 0x80)
|
||
IOWR_OUT(I2C_SDA, 1);
|
||
else
|
||
IOWR_OUT(I2C_SDA, 0);
|
||
delay_us(5);
|
||
IOWR_OUT(I2C_SCL, 1);
|
||
delay_us(5);
|
||
IOWR_OUT(I2C_SCL, 0);
|
||
delay_us(5);
|
||
IIC_Byte <<= 1;
|
||
}
|
||
delay_us(5);
|
||
IOWR_OUT(I2C_SDA, 1);
|
||
delay_us(5);
|
||
IOWR_OUT(I2C_SCL, 1);
|
||
delay_us(5);
|
||
IOWR_OUT(I2C_SCL, 0);
|
||
delay_us(5);
|
||
}
|
||
|
||
// 主控端对从机读取一个字节
|
||
static unsigned char CH455_I2C_RdByte(void) // 读取一个字节数据
|
||
{
|
||
unsigned char i = 0;
|
||
unsigned char bytedata = 0;
|
||
delay_us(5);
|
||
// 将数据设置为输入模式
|
||
IOWR_IN(I2C_SDA, 1);
|
||
delay_us(5);
|
||
IOWR_OUT(I2C_SCL, 0);
|
||
delay_us(5);
|
||
for (i = 0; i < 8; i++)
|
||
{
|
||
IOWR_OUT(I2C_SCL, 1);
|
||
delay_us(5);
|
||
bytedata <<= 1;
|
||
delay_us(5);
|
||
bytedata = bytedata | (IORD(I2C_SDA));
|
||
delay_us(5);
|
||
IOWR_OUT(I2C_SCL, 0);
|
||
delay_us(5);
|
||
}
|
||
IOWR_OUT(I2C_SDA, 1); // 数据线设置回输出模式
|
||
delay_us(5);
|
||
IOWR_OUT(I2C_SCL, 1);
|
||
delay_us(5);
|
||
IOWR_OUT(I2C_SCL, 0);
|
||
delay_us(5);
|
||
return (bytedata); // 返回数据
|
||
}
|
||
|
||
// 写命令
|
||
static unsigned char CH455_Write(UINT16 cmd)
|
||
{
|
||
printf("CH455_Write start...\n");
|
||
CH455_I2c_Start(); // 启动总线
|
||
printf("CH455_Write first byte= %02x\n", ((UINT8)(cmd >> 7) & CH455_I2C_MASK) | CH455_I2C_ADDR);
|
||
printf("CH455_Write second byte= %02x\n", (UINT8)cmd);
|
||
CH455_I2C_WrByte(((UINT8)(cmd >> 7) & CH455_I2C_MASK) | CH455_I2C_ADDR);
|
||
CH455_I2C_WrByte((UINT8)cmd); // 发送数据
|
||
CH455_I2c_Stop(); // 结束总线
|
||
printf("CH455_Write end...\n");
|
||
printf("\n");
|
||
return 1;
|
||
}
|
||
|
||
static unsigned char CH455_Read(void) // 读取按键值
|
||
{
|
||
printf("CH455_Read start...\n");
|
||
UINT8 keycode;
|
||
CH455_I2c_Start(); // 启动总线
|
||
printf("write byte= %02x\n", (UINT8)(CH455_GET_KEY >> 7) & CH455_I2C_MASK | 0x01 | CH455_I2C_ADDR);
|
||
CH455_I2C_WrByte((UINT8)(CH455_GET_KEY >> 7) & CH455_I2C_MASK | 0x01 | CH455_I2C_ADDR);
|
||
keycode = CH455_I2C_RdByte(); // 读取数据
|
||
printf("read byte= %02x\n", keycode);
|
||
CH455_I2c_Stop(); // 结束总线
|
||
printf("CH455_Read end...\n");
|
||
printf("\n");
|
||
return keycode;
|
||
}
|
||
|
||
void key_Inter(void)
|
||
{
|
||
int ret;
|
||
int val = 0;
|
||
char buf[8];
|
||
int num;
|
||
UINT16 key_value;
|
||
pollfd pfd;
|
||
pfd.fd = -1;
|
||
pfd.fd = open("/sys/class/gpio/gpio52/value", O_RDONLY);
|
||
if (pfd.fd > 0)
|
||
printf("huagao::open sucess,fd = %d\n", pfd.fd);
|
||
else
|
||
printf("huagao::open failed,fd = %d\n", pfd.fd);
|
||
pfd.events = POLLPRI;
|
||
num = read(pfd.fd, buf, 8); // This is to clear the avaible read
|
||
for (int i = 0; i < 8; i++)
|
||
printf("huagao::buf[%d] = %d\n", i, buf[i]);
|
||
|
||
ret = CH455_Write(CH455_SYSON);
|
||
printf("CH455_SYSON = %02x\n", (CH455_SYSON));
|
||
printf("CH455_Read() = %02x\n", CH455_Read());
|
||
key_value = 0xff;
|
||
while (1)
|
||
{
|
||
ret = poll(&pfd, 1, 1000);
|
||
if (ret > 0)
|
||
{
|
||
printf("--------------------------------------------\n");
|
||
printf("huagao::poll get date.\n");
|
||
printf("huagao::poll ret = %d\n", ret);
|
||
/*
|
||
POLLIN: 有普通数据或者优先数据可读
|
||
POLLRDNORM: 有普通数据可读
|
||
POLLRDBAND: 有优先数据可读
|
||
POLLPRI: 有紧急数据可读
|
||
POLLOUT: 有普通数据可写
|
||
POLLWRNORM: 有普通数据可写
|
||
POLLWRBAND: 有紧急数据可写
|
||
POLLERR: 有错误发生
|
||
POLLHUP: 有描述符挂起事件发生
|
||
POLLNVAL: 描述符非法
|
||
*/
|
||
if (pfd.revents & POLLPRI)
|
||
{
|
||
lseek(pfd.fd, 0, SEEK_SET);
|
||
num = read(pfd.fd, buf, 8);
|
||
buf[num - 1] = '\0';
|
||
ret = atoi(buf);
|
||
for (int i = 0; i < 8; i++)
|
||
printf("huagao::buf[%d] = %d\n", i, buf[i]);
|
||
printf("huagao::atoi(buf) ret = %d\n", ret);
|
||
}
|
||
key_value = CH455_Read();
|
||
printf("CH455_Read() = %02x\n", key_value);
|
||
printf("--------------------------------------------\n");
|
||
printf("\n");
|
||
}
|
||
else if (ret == 0)
|
||
{
|
||
printf("--------------------------------------------\n");
|
||
printf("huagao::ret = %d\n", ret);
|
||
printf("huagao::poll time out.\n");
|
||
printf("--------------------------------------------\n");
|
||
printf("\n");
|
||
}
|
||
else
|
||
{
|
||
printf("--------------------------------------------\n");
|
||
printf("huagao::ret = %d\n", ret);
|
||
printf("huagao::poll err.\n");
|
||
printf("--------------------------------------------\n");
|
||
printf("\n");
|
||
}
|
||
}
|
||
}
|
||
int main(void)
|
||
{
|
||
system("echo 52 > /sys/class/gpio/export");
|
||
system("echo in > /sys/class/gpio/gpio52/direction");
|
||
system("echo falling > /sys/class/gpio/gpio52/edge");
|
||
key_Inter();
|
||
return 0;
|
||
}
|