news 2026/4/25 1:26:17

海思3531d使用gpio模拟i2c

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
海思3531d使用gpio模拟i2c

使用gpio模拟i2c读写16位位宽寄存器

芯片i2c时序如下

#include <linux/module.h> #include <linux/errno.h> #include <linux/miscdevice.h> #include <linux/fcntl.h> #include <linux/uaccess.h> #include <linux/io.h> #include <linux/gpio/consumer.h> #include <linux/init.h> #include <linux/delay.h> #include <linux/proc_fs.h> #include <linux/workqueue.h> #define I2C_SCL 46 #define I2C_SDA 45 struct gpio_desc *i2c_scl_desc; struct gpio_desc *i2c_sda_desc; #define GPIO_I2C_READ 0x01 #define GPIO_I2C_WRITE 0x02 #define GPIO_I2C_READ16 0x03 #define GPIO_I2C_WRITE16 0x04 typedef struct _mul_i2c { int addr; int val; }multi_i2c_s; void gpio_i2c_multi_write16(unsigned char devaddress, unsigned short address, unsigned short *data, unsigned short bytes); unsigned short gpio_i2c_read16(unsigned char devaddress, unsigned short address); void gpio_i2c_write16(unsigned char devaddress, unsigned short address, unsigned short data); void gpio_i2c_multi_read16(unsigned char devaddress, unsigned short address, unsigned short *data, unsigned short bytes); void i2c_start(void) { gpiod_direction_output(i2c_scl_desc, 1); gpiod_direction_output(i2c_sda_desc, 1); udelay(2); gpiod_direction_output(i2c_sda_desc, 0); udelay(2); gpiod_direction_output(i2c_scl_desc, 0); udelay(2); } void i2c_stop(void) { gpiod_direction_output(i2c_scl_desc, 0); gpiod_direction_output(i2c_sda_desc, 0); udelay(2); gpiod_direction_output(i2c_scl_desc, 1); udelay(2); gpiod_direction_output(i2c_sda_desc, 1); udelay(2); } void i2c_send_ack(int ack) { gpiod_direction_output(i2c_sda_desc, 0); if (ack) { gpiod_direction_output(i2c_sda_desc, 0); } else { gpiod_direction_output(i2c_sda_desc, 1); } gpiod_direction_output(i2c_scl_desc, 1); udelay(2); gpiod_direction_output(i2c_scl_desc, 0); } int i2c_recv_ack(void) { int value = 0; gpiod_direction_input(i2c_sda_desc); gpiod_direction_output(i2c_scl_desc, 1); udelay(2); if (gpiod_get_value(i2c_sda_desc)) { value = 1; } else { value = 0; } gpiod_direction_output(i2c_scl_desc, 0); gpiod_direction_output(i2c_sda_desc, 1); return value; } void i2c_send_data(int data) { int i; int value; gpiod_direction_output(i2c_scl_desc, 0); for (i = 0; i < 8; i++) { value = (data << i) & 0x80; if (value) { gpiod_direction_output(i2c_sda_desc, 1); } else { gpiod_direction_output(i2c_sda_desc, 0); } gpiod_direction_output(i2c_scl_desc, 1); udelay(2); gpiod_direction_output(i2c_scl_desc, 0); udelay(2); } } int i2c_recv_data(void) { int i; int temp = 0; int data = 0; gpiod_direction_input(i2c_sda_desc); udelay(2); for (i = 0; i < 8; i++) { gpiod_direction_output(i2c_scl_desc, 0); udelay(2); gpiod_direction_output(i2c_scl_desc, 1); udelay(2); data = gpiod_get_value(i2c_sda_desc); if (data) { temp = (temp << 1) | data; } else { temp = (temp << 1) & ~data; } } gpiod_direction_output(i2c_scl_desc, 0); udelay(2); gpiod_direction_output(i2c_sda_desc, 1); return temp; } EXPORT_SYMBOL(gpio_i2c_multi_read16); void gpio_i2c_multi_read16(unsigned char devaddress, unsigned short address, unsigned short *data, unsigned short bytes) { unsigned short i; unsigned short rxdata; unsigned char high,low; if (bytes < 2) return; devaddress &= 0xFE; i2c_start(); i2c_send_data(devaddress); i2c_recv_ack(); high = (address&0xff00)>>8; low = address&0xff; i2c_send_data(high); i2c_recv_ack(); i2c_send_data(low); i2c_recv_ack(); i2c_start(); i2c_send_data(devaddress | 1); i2c_recv_ack(); for(i=0; i<(bytes-2)/2; i++) { high= i2c_recv_data(); i2c_send_ack(1); low = i2c_recv_data(); i2c_send_ack(1); data[i] = (high<<8)|low; } high= i2c_recv_data(); i2c_send_ack(1); low = i2c_recv_data(); i2c_send_ack(0); data[i] = (high<<8)|low; i2c_stop(); // rxdata=(high<<8)|low; // return rxdata; } EXPORT_SYMBOL(gpio_i2c_multi_write16); void gpio_i2c_multi_write16(unsigned char devaddress, unsigned short address, unsigned short *data, unsigned short bytes) { unsigned short i; unsigned char high, low; if (bytes < 2) return; i2c_start(); devaddress &= 0xFE; i2c_send_data(devaddress); i2c_recv_ack(); high = (address&0xff00)>>8; low = address&0xff; i2c_send_data(high); i2c_recv_ack(); i2c_send_data(low); i2c_recv_ack(); i2c_start(); i2c_send_data(devaddress); i2c_recv_ack(); for(i=0; i<bytes/2; i++) { high = (data[i]&0xff00)>>8; low = data[i]&0xff; i2c_send_data(high); i2c_recv_ack(); i2c_send_data(low); i2c_recv_ack(); } i2c_stop(); } EXPORT_SYMBOL(gpio_i2c_read16); unsigned short gpio_i2c_read16(unsigned char devaddress, unsigned short address) { unsigned short rxdata; unsigned char high,low; devaddress &= 0xFE; i2c_start(); i2c_send_data(devaddress); i2c_recv_ack(); high = (address&0xff00)>>8; low = address&0xff; i2c_send_data(high); i2c_recv_ack(); i2c_send_data(low); i2c_recv_ack(); i2c_start(); i2c_send_data(devaddress | 1); i2c_recv_ack(); high= i2c_recv_data(); i2c_send_ack(1); low = i2c_recv_data(); i2c_send_ack(0);//nack // printk("hi=0x%x,low=0x%x\n",high,low); i2c_stop(); // rxdata=0; rxdata=(high<<8)|low; return rxdata; } EXPORT_SYMBOL(gpio_i2c_write16); void gpio_i2c_write16(unsigned char devaddress, unsigned short address, unsigned short data) { unsigned char high,low; devaddress &= 0xFE; i2c_start(); i2c_send_data(devaddress); i2c_recv_ack(); high = (address&0xff00)>>8; low = address&0xff; i2c_send_data(high); i2c_recv_ack(); i2c_send_data(low); i2c_recv_ack(); i2c_start(); i2c_send_data(devaddress); i2c_recv_ack(); high = (data&0xff00)>>8; low = data&0xff; i2c_send_data(high); i2c_recv_ack(); i2c_send_data(low); i2c_recv_ack(); i2c_stop(); } int gpioi2c_open(struct inode * inode, struct file * file) { return 0; } int gpioi2c_close(struct inode * inode, struct file * file) { return 0; } long gpioi2c_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { unsigned int val; unsigned int __user *argp = (unsigned int __user *)arg; unsigned char device_addr; int reg_addr16; unsigned short reg_val; multi_i2c_s multi_i2c_arg; switch(cmd) { case GPIO_I2C_READ16: if (copy_from_user(&val, argp, sizeof(val))) { printk("GPIO_I2C_WRITE16: WRONG cpy multi_i2c_arg \n"); return -1; } //printk("ioctl read val=0x%x\n",val); device_addr = (val&0xff0000)>>16; reg_addr16 = (val&0xffff); reg_val = gpio_i2c_read16(device_addr, reg_addr16); //*(unsigned int *)arg = reg_val; val = reg_val; if (copy_to_user(argp, &val, sizeof(val))) { return -1; } break; case GPIO_I2C_WRITE16: if (copy_from_user(&multi_i2c_arg, argp, sizeof(multi_i2c_arg))) { printk("GPIO_I2C_WRITE16: WRONG cpy multi_i2c_arg \n"); return -1; } device_addr = (multi_i2c_arg.addr&0xff0000)>>16; reg_addr16 = (multi_i2c_arg.addr&0xffff); reg_val = multi_i2c_arg.val&0xffff; gpio_i2c_write16(device_addr, reg_addr16, reg_val); break; } return 0; } static struct file_operations gpioi2c_fops = { .owner = THIS_MODULE, .unlocked_ioctl = gpioi2c_ioctl, .open = gpioi2c_open, .release = gpioi2c_close }; static struct miscdevice gpioi2c_dev = { .minor = MISC_DYNAMIC_MINOR, .name = "gpioi2c", .fops = &gpioi2c_fops, }; static int gpio_i2c_init(void) { int ret; ret = misc_register(&gpioi2c_dev); if(0 != ret) return -1; i2c_scl_desc = gpio_to_desc(I2C_SCL); if (i2c_scl_desc == NULL) { printk("gpio_to_desc error for SCL pin\n"); return -1; } i2c_sda_desc = gpio_to_desc(I2C_SDA); if (i2c_sda_desc == NULL) { printk("gpio_to_desc error for SDA pin\n"); return -1; } gpiod_direction_output(i2c_scl_desc, 1); gpiod_direction_output(i2c_sda_desc, 1); //ft5x06_write_reg(0x38,0x80,0x33); //ft5x06_read_reg(0x38,0x80); return 0; } static void gpio_i2c_exit(void) { misc_deregister(&gpioi2c_dev); gpiod_put(i2c_scl_desc); gpiod_put(i2c_sda_desc); } module_init(gpio_i2c_init); module_exit(gpio_i2c_exit); MODULE_LICENSE("GPL");
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/25 1:24:42

N_m3u8DL-RE跨平台流媒体下载器深度架构解析与实战技术指南

N_m3u8DL-RE跨平台流媒体下载器深度架构解析与实战技术指南 【免费下载链接】N_m3u8DL-RE Cross-Platform, modern and powerful stream downloader for MPD/M3U8/ISM. English/简体中文/繁體中文. 项目地址: https://gitcode.com/GitHub_Trending/nm3/N_m3u8DL-RE 在当…

作者头像 李华
网站建设 2026/4/25 1:24:41

为什么你的VSCode无法连接J-Link?揭秘嵌入式调试链路中被忽视的3层协议栈配置(CMSIS-DAP/OpenOCD/JLinkGDBServer深度对比)

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;VSCode嵌入式调试配置全景概览 VSCode 作为轻量级但高度可扩展的编辑器&#xff0c;已成为嵌入式开发者的主流调试平台。其核心能力依赖于三类组件协同工作&#xff1a;C/C 扩展&#xff08;提供语言支…

作者头像 李华
网站建设 2026/4/25 1:24:40

C语言完美演绎8-18

/* 范例&#xff1a;8-18 */#include <stdio.h>void procreation(int,void (*run)(char*,int)); /* 以函数指针为参数 */void slow_run_shoes(char*,int);void leisure_shoes(char*,int);void spiked_shoes(char*,int);void main(){int procreation_number; /* 生产项…

作者头像 李华
网站建设 2026/4/25 1:23:39

跨平台音乐格式转换终极实战:Unlock-Music音频优化技术深度解析

跨平台音乐格式转换终极实战&#xff1a;Unlock-Music音频优化技术深度解析 【免费下载链接】unlock-music 在浏览器中解锁加密的音乐文件。原仓库&#xff1a; 1. https://github.com/unlock-music/unlock-music &#xff1b;2. https://git.unlock-music.dev/um/web 项目地…

作者头像 李华
网站建设 2026/4/25 1:22:35

面向软件测试从业者的代码遗产系统化托管方案

在软件开发的漫长生命周期中&#xff0c;每一个活跃项目都终将步入其成熟或衰退期&#xff0c;而伴随这一过程产生的大量“代码遗产”——即那些仍在运行但缺乏活跃维护、文档不全、技术栈陈旧的系统代码——已成为软件测试从业者必须面对的核心挑战之一。这些系统往往承载着企…

作者头像 李华