chinese直男口爆体育生外卖, 99久久er热在这里只有精品99, 又色又爽又黄18禁美女裸身无遮挡, gogogo高清免费观看日本电视,私密按摩师高清版在线,人妻视频毛茸茸,91论坛 兴趣闲谈,欧美 亚洲 精品 8区,国产精品久久久久精品免费

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Linux驅(qū)動(dòng)開(kāi)發(fā)-編寫(xiě)(EEPROM)AT24C02驅(qū)動(dòng)

DS小龍哥-嵌入式技術(shù) ? 2022-09-17 15:29 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

【摘要】 AT24C02是IIC接口的EEPROM存儲(chǔ)芯片,這顆芯片非常經(jīng)典,百度搜索可以找到非常多的資料,大多都是51、STM32單片機(jī)的示例代碼,大多采用模擬時(shí)序、裸機(jī)系統(tǒng)運(yùn)行。當(dāng)前文章介紹在Linux系統(tǒng)里如何編寫(xiě)AT24C02的驅(qū)動(dòng),并且在應(yīng)用層完成驅(qū)動(dòng)讀寫(xiě)測(cè)試,將AT24C02的存儲(chǔ)空間映射成文件,在應(yīng)用層,用戶(hù)可以直接將AT24C02當(dāng)做一個(gè)普通文件的形式進(jìn)行讀寫(xiě),偏移文件指針;在Linux內(nèi)核

1. 前言

AT24C02是IIC接口的EEPROM存儲(chǔ)芯片,這顆芯片非常經(jīng)典,百度搜索可以找到非常多的資料,大多都是51、STM32單片機(jī)的示例代碼,大多采用模擬時(shí)序、裸機(jī)系統(tǒng)運(yùn)行。當(dāng)前文章介紹在Linux系統(tǒng)里如何編寫(xiě)AT24C02的驅(qū)動(dòng),并且在應(yīng)用層完成驅(qū)動(dòng)讀寫(xiě)測(cè)試,將AT24C02的存儲(chǔ)空間映射成文件,在應(yīng)用層,用戶(hù)可以直接將AT24C02當(dāng)做一個(gè)普通文件的形式進(jìn)行讀寫(xiě),偏移文件指針;在Linux內(nèi)核里有一套標(biāo)準(zhǔn)的IIC子系統(tǒng)框架專(zhuān)門(mén)讀寫(xiě)IIC接口設(shè)備,采用平臺(tái)設(shè)備模型框架,編寫(xiě)驅(qū)動(dòng)非常方便。

當(dāng)前開(kāi)發(fā)板采用友善之臂的Tiny4412,CPU三星的EXYNOS4412,4412是三星的第一款四核處理器,主頻是1.5GHZ,穩(wěn)定頻率是1.4GHZ。

2. 硬件原理圖

當(dāng)前的開(kāi)發(fā)板上自帶了一顆EEPROM存儲(chǔ)芯片(具體型號(hào)是24AA025E48,代碼與AT24C02一樣的),原理圖如下:

image-20220104085514044image-20220104085817035

自帶的內(nèi)核里沒(méi)有內(nèi)置EEPROM的驅(qū)動(dòng):

image-20220104085843239

存儲(chǔ)芯片的數(shù)據(jù)手冊(cè)介紹:

image-20220104090012199

設(shè)備地址:

image-20220104090059967

寫(xiě)字節(jié)、頁(yè)寫(xiě)時(shí)序:

image-20220104090126403

讀數(shù)據(jù)時(shí)序:

image-20220104090200161

3. 示例代碼

3.1 EEPROM驅(qū)動(dòng)端代碼

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
static struct work_struct work;
static struct i2c_client *eeprom_client;

#define MAX_SIZE 255  //EEPROM大小
#define EEPROM_PAGE  16 //頁(yè)字節(jié)大小

static u8 eeprom_buff[255];
static int tiny4412_open(struct inode *inode, struct file *file)
{
	printk("tiny4412_open-->ok\n");
	return 0;
}

static ssize_t tiny4412_read(struct file *file, char __user *buf, size_t size, loff_t *seek)
{	
	unsigned long err;
	//判斷位置是否超出范圍
	if(*seek+size>MAX_SIZE)
	{
		size=MAX_SIZE-*seek;
	}
	//讀取數(shù)據(jù)
	i2c_smbus_read_i2c_block_data(eeprom_client,*seek,size,eeprom_buff);
	err=copy_to_user(buf,eeprom_buff,size);
	if(err!=0)return -1;
	*seek+=size;
	return size;
}

static ssize_t tiny4412_write(struct file *file, const char __user *buf, size_t size, loff_t *seek)
{
	size_t write_ok_cnt=0;
	unsigned long err;
	err=copy_from_user(eeprom_buff,buf,size);
	if(err!=0)return -1;
	//判斷位置是否超出范圍
	if(*seek+size>MAX_SIZE)
	{
		size=MAX_SIZE-*seek;
	}
	
	int write_byte=0;
	u8 *write_p=eeprom_buff;
	while(1)
	{
		if(size>EEPROM_PAGE)
		{
			write_byte=EEPROM_PAGE;
			size-=EEPROM_PAGE;
		}
		else
		{
			write_byte=size;
		}
		
		//寫(xiě)數(shù)據(jù)
		i2c_smbus_write_i2c_block_data(eeprom_client,*seek,write_byte,write_p);
		*seek+=write_byte;
		write_p+=write_byte;
		write_ok_cnt+=write_byte;  //記錄寫(xiě)成功的字節(jié)數(shù)
		//等待寫(xiě)完成
		msleep(10);
		if(write_byte==size)break; //寫(xiě)完畢
	}
	return write_ok_cnt;
}

/*
filp:待操作的設(shè)備文件file結(jié)構(gòu)體指針
off:待操作的定位偏移值(可正可負(fù))
whence:待操作的定位起始位置
返回:返回移位后的新文件讀、寫(xiě)位置,并且新位置總為正值
定位起始位置
  SEEK_SET:0,表示文件開(kāi)頭
  SEEK_CUR:1,表示當(dāng)前位置
  SEEK_END:2,表示文件尾
*/
static loff_t tiny4412_llseek(struct file *filp, loff_t offset, int whence)
{
	loff_t newpos = 0;
	switch(whence)
	{
		case SEEK_SET:
			newpos = offset;
			break;
		case SEEK_CUR:
			newpos = filp->f_pos + offset;
			break;
		case SEEK_END:
			if(MAX_SIZE+offset>=MAX_SIZE)
			{
				newpos=MAX_SIZE;
			}
			else
			{
				newpos = MAX_SIZE + offset;
			}
			break;
		default:
			return -EINVAL;//無(wú)效的參數(shù)
	}
	filp->f_pos = newpos;
	return newpos;
}

static int tiny4412_release(struct inode *inode, struct file *file)
{
	printk("tiny4412_release-->ok\n");
	return 0;
}

static struct file_operations fops=
{
	.open=tiny4412_open,
	.read=tiny4412_read,
	.write=tiny4412_write,
	.release=tiny4412_release,
	.llseek=tiny4412_llseek
};

/*
Linux內(nèi)核管理驅(qū)動(dòng)---設(shè)備號(hào)
設(shè)備號(hào)是一個(gè)unsigned int 的變量--32位。
設(shè)備號(hào)=主設(shè)備號(hào)+次設(shè)備號(hào)
*/
static struct miscdevice misc=
{
	.minor = MISC_DYNAMIC_MINOR,  /*次設(shè)備號(hào)填255表示自動(dòng)分配     主設(shè)備號(hào)固定為10*/
	.name = "tiny4412_eeprom",  /*/dev目錄下文件名稱(chēng)*/
	.fops = &fops, /*文件操作接口*/
};
static int tiny4412_probe(struct i2c_client *client, const struct i2c_device_id *device_id)
{
	printk("probe調(diào)用成功:%#X\n",client->addr);
	eeprom_client=client;
	
	/*1. 雜項(xiàng)設(shè)備的注冊(cè)函數(shù)*/
	misc_register(&misc);
	
	return 0;
}

static int tiny4412_remove(struct i2c_client *client)
{
	/*2. 雜項(xiàng)設(shè)備的注銷(xiāo)函數(shù)*/
	misc_deregister(&misc);
	printk("remove調(diào)用成功.\n");
	return 0;
}

static struct i2c_device_id id_table[]=
{
	{"tiny4412_eeprom",0},
	{}
};

static struct i2c_driver drv=
{
	.probe=tiny4412_probe,
	.remove=tiny4412_remove,
	.driver=
	{
		.name="eeprom_iic"
	},
	.id_table=id_table
};

static int __init tiny4412_drv_init(void)
{	
	/*注冊(cè)IIC驅(qū)動(dòng)端*/
	i2c_add_driver(&drv);
    printk("IIC驅(qū)動(dòng)端: 驅(qū)動(dòng)安裝成功\n");
    return 0;
}

static void __exit tiny4412_drv_cleanup(void)
{
	/*注銷(xiāo)IIC驅(qū)動(dòng)端*/
	i2c_del_driver(&drv);
    printk("IIC驅(qū)動(dòng)端: 驅(qū)動(dòng)卸載成功\n");
}

module_init(tiny4412_drv_init);    /*驅(qū)動(dòng)入口--安裝驅(qū)動(dòng)的時(shí)候執(zhí)行*/
module_exit(tiny4412_drv_cleanup); /*驅(qū)動(dòng)出口--卸載驅(qū)動(dòng)的時(shí)候執(zhí)行*/

MODULE_LICENSE("GPL");  /*設(shè)置模塊的許可證--GPL*/

3.2 EEPROM設(shè)備端代碼

#include 
#include 
#include 
#include 
#include 
#include 
#include 

static struct i2c_client *i2c_dev=NULL;
static struct i2c_adapter *adap=NULL;
static struct i2c_board_info info=
{
	.type="tiny4412_eeprom",
	.addr=0x50, /*設(shè)備地址*/
};

static int __init tiny4412_drv_init(void)
{	
	/*根據(jù)總線編號(hào)獲取是適配器*/
	adap=i2c_get_adapter(0);
	/*注冊(cè)IIC設(shè)備端*/
	i2c_dev=i2c_new_device(adap,&info);
    printk("IIC設(shè)備端: 驅(qū)動(dòng)安裝成功\n");
    return 0;
}

static void __exit tiny4412_drv_cleanup(void)
{
	/*注銷(xiāo)IIC設(shè)備*/
	i2c_unregister_device(i2c_dev);
	i2c_put_adapter(adap);
    printk("IIC設(shè)備端: 驅(qū)動(dòng)卸載成功\n");
}

module_init(tiny4412_drv_init);    /*驅(qū)動(dòng)入口--安裝驅(qū)動(dòng)的時(shí)候執(zhí)行*/
module_exit(tiny4412_drv_cleanup); /*驅(qū)動(dòng)出口--卸載驅(qū)動(dòng)的時(shí)候執(zhí)行*/

MODULE_LICENSE("GPL");  /*設(shè)置模塊的許可證--GPL*/

3.3 應(yīng)用層測(cè)試代碼

#include 
#include 
#include 
#include 

#define EEPROM_DEV "/dev/tiny4412_eeprom"

int main(int argc,char **argv)
{
    /*1. 打開(kāi)設(shè)備文件*/
    int fd=open(EEPROM_DEV,O_RDWR);
    if(fd<0)
    {
        printf("%s 設(shè)備驅(qū)動(dòng)打開(kāi)失敗.\n",EEPROM_DEV);
        return 0;
	}
    /*3.讀寫(xiě)數(shù)據(jù)*/
	unsigned char buff[255];
	int cnt;
	int i;
	for(i=0;i<255;i++)buff[i]=i;
	cnt=write(fd,buff,255);
    printf("write成功:%d Byte\n",cnt);
	
	//偏移文件指針
	lseek(fd,SEEK_SET,0);
	
	unsigned char buff_r[255];
	cnt=read(fd,buff_r,255);
	printf("read成功:%d Byte\n",cnt);
	for(i=0;i;i++)>
聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 驅(qū)動(dòng)
    +關(guān)注

    關(guān)注

    12

    文章

    1927

    瀏覽量

    88172
  • EEPROM
    +關(guān)注

    關(guān)注

    9

    文章

    1127

    瀏覽量

    85485
  • AT24C02
    +關(guān)注

    關(guān)注

    0

    文章

    79

    瀏覽量

    25025
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    迅為iTOP-3568開(kāi)發(fā)板?Linux驅(qū)動(dòng)開(kāi)發(fā)實(shí)戰(zhàn):menuconfig圖形化配置實(shí)驗(yàn)

    迅為iTOP-3568開(kāi)發(fā)板?Linux驅(qū)動(dòng)開(kāi)發(fā)實(shí)戰(zhàn):menuconfig圖形化配置實(shí)驗(yàn)
    的頭像 發(fā)表于 11-24 15:29 ?477次閱讀
    迅為iTOP-3568<b class='flag-5'>開(kāi)發(fā)</b>板?<b class='flag-5'>Linux</b><b class='flag-5'>驅(qū)動(dòng)</b><b class='flag-5'>開(kāi)發(fā)</b>實(shí)戰(zhàn):menuconfig圖形化配置實(shí)驗(yàn)

    【免費(fèi)送書(shū)】成為硬核Linux開(kāi)發(fā)者:《Linux 設(shè)備驅(qū)動(dòng)開(kāi)發(fā)(第 2 版)》

    Linux系統(tǒng)的設(shè)備驅(qū)動(dòng)開(kāi)發(fā),一直給人門(mén)檻較高的印象,主要因內(nèi)核機(jī)制抽象、需深度理解硬件原理、開(kāi)發(fā)調(diào)試難度大所致。2021年,一本講解驅(qū)動(dòng)
    的頭像 發(fā)表于 11-18 08:06 ?396次閱讀
    【免費(fèi)送書(shū)】成為硬核<b class='flag-5'>Linux</b><b class='flag-5'>開(kāi)發(fā)</b>者:《<b class='flag-5'>Linux</b> 設(shè)備<b class='flag-5'>驅(qū)動(dòng)</b><b class='flag-5'>開(kāi)發(fā)</b>(第 2 版)》

    【書(shū)籍評(píng)測(cè)活動(dòng)NO.67】成為硬核Linux開(kāi)發(fā)者:《Linux 設(shè)備驅(qū)動(dòng)開(kāi)發(fā)(第 2 版)》

    時(shí)代的硬核技能。現(xiàn)在,我們從零起步,進(jìn)入Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)的世界吧。從零開(kāi)始學(xué)會(huì)Linux設(shè)備驅(qū)動(dòng)開(kāi)
    發(fā)表于 11-17 17:52

    串行EEPROM P24C256H產(chǎn)品介紹

    P24C256H是I2C兼容的串行EEPROM(電可擦除可編程存儲(chǔ)器)設(shè)備。它包含一個(gè)256Kbits (32Kbytes)的內(nèi)存陣列,每頁(yè)64bytes。
    的頭像 發(fā)表于 08-08 17:05 ?1694次閱讀
    串行<b class='flag-5'>EEPROM</b> P<b class='flag-5'>24C</b>256H產(chǎn)品介紹

    【沁恒CH585開(kāi)發(fā)板免費(fèi)試用體驗(yàn)】I2C 讀寫(xiě)EEPROM (三)

    ) { goto cmd_fail; /* EEPROM器件無(wú)應(yīng)答 */ } /* 第4步:發(fā)送字節(jié)地址,24C02只有256字節(jié),因此1個(gè)字節(jié)就夠了,如果是24C04以上,那么此處需要連發(fā)多個(gè)地址
    發(fā)表于 08-05 22:25

    【沁恒CH585開(kāi)發(fā)板免費(fèi)試用體驗(yàn)】I2C 讀寫(xiě)EEPROM (二)

    寫(xiě)不同的是,數(shù)據(jù)會(huì)一直發(fā),直到主機(jī)發(fā)送停止信號(hào)。 /** * @brief在EEPROM的一個(gè)寫(xiě)循環(huán)中可以寫(xiě)多個(gè)字節(jié),但一次寫(xiě)入的字節(jié)數(shù) * 不能超過(guò)EEPROM頁(yè)的大小,AT24C02每頁(yè)有8個(gè)字
    發(fā)表于 08-05 22:13

    單片機(jī)實(shí)例項(xiàng)目:AT24C02EEPROM存儲(chǔ)器

    單片機(jī)實(shí)例項(xiàng)目:AT24C02EEPROM存儲(chǔ)器,推薦下載!
    發(fā)表于 06-03 20:50

    itop-3568開(kāi)發(fā)驅(qū)動(dòng)開(kāi)發(fā)指南-實(shí)驗(yàn)程序的編寫(xiě)

    驅(qū)動(dòng)例程\\\\02。 本章實(shí)驗(yàn)將編寫(xiě) Linux 下的驅(qū)動(dòng)傳參實(shí)例代碼,通過(guò)“insmod”命令進(jìn)行參數(shù)的傳遞,并將相應(yīng)的參數(shù)打印到串口
    發(fā)表于 05-19 10:26

    【RA-Eco-RA4M2開(kāi)發(fā)板評(píng)測(cè)】I2C讀取EEPROM(二)

    */ i2c_event = p_args->event; } } 主要配置I2C模式、低電平占空比、I2C尋址模式以及通信速率,最后使能I2C設(shè)備。 初始化完成后就是對(duì)
    發(fā)表于 04-28 23:14

    基于APM32F407如何制作I2C EEPROMAT24C02型號(hào))的MDK-Keil下載算法

    基于APM32F407如何制作I2C EEPROMAT24C02型號(hào))的Keil下載算法,這樣在我們下載代碼時(shí)可以一鍵把數(shù)據(jù)燒錄到EEPROM中。
    的頭像 發(fā)表于 04-11 11:06 ?1748次閱讀
    基于APM32F407如何制作I2<b class='flag-5'>C</b> <b class='flag-5'>EEPROM</b>(<b class='flag-5'>AT24C02</b>型號(hào))的MDK-Keil下載算法

    迅為RK3568開(kāi)發(fā)板helloworld 驅(qū)動(dòng)實(shí)驗(yàn)-驅(qū)動(dòng)編寫(xiě)

    在學(xué)習(xí) C 語(yǔ)言或者其他語(yǔ)言的時(shí)候,我們通常是打印一句“helloworld”來(lái)開(kāi)啟編程世界的大門(mén)。學(xué)習(xí)驅(qū)動(dòng)程序編程亦可以如此,使用 helloworld 作為我們的第一個(gè)驅(qū)動(dòng)程序。接下來(lái)開(kāi)始
    發(fā)表于 04-01 15:20

    【CW32模塊使用】AT24C02-EEPROM存儲(chǔ)器

    可以在電腦上或?qū)S迷O(shè)備上擦除已有信息,重新編程。一般用在即插即用。AT24C02是一個(gè)2K位串行CMOS E2PROM, 內(nèi)部含有256個(gè)8位字節(jié),CATALYST公司的先進(jìn)CMOS技術(shù)實(shí)質(zhì)上減少
    的頭像 發(fā)表于 03-29 17:26 ?1398次閱讀
    【CW32模塊使用】AT<b class='flag-5'>24C02-EEPROM</b>存儲(chǔ)器

    STM32F407的兩個(gè)USB口能否分別實(shí)現(xiàn)讀卡器和讀U盤(pán)的功能以及硬件IIC讀寫(xiě)AT24C02?

    需求如下: 1.OTS_FS(PA 11,PA12)實(shí)現(xiàn)TF卡的讀卡器功能, 2.OTS_HS(PB14,PB15)實(shí)現(xiàn)讀寫(xiě)U盤(pán)功能 3.硬件IIC(PB8,PB9)讀寫(xiě)AT24C02,硬件IIC是否有BUG? 以上是否有相關(guān)的庫(kù)例程? 謝謝!
    發(fā)表于 03-11 06:23

    迅為RK3568開(kāi)發(fā)驅(qū)動(dòng)指南Linux中通用SPI設(shè)備驅(qū)動(dòng)

    迅為RK3568開(kāi)發(fā)驅(qū)動(dòng)指南Linux中通用SPI設(shè)備驅(qū)動(dòng)
    的頭像 發(fā)表于 01-23 11:02 ?3403次閱讀
    迅為RK3568<b class='flag-5'>開(kāi)發(fā)</b>板<b class='flag-5'>驅(qū)動(dòng)</b>指南<b class='flag-5'>Linux</b>中通用SPI設(shè)備<b class='flag-5'>驅(qū)動(dòng)</b>

    迅為RK3568開(kāi)發(fā)板SPI驅(qū)動(dòng)指南-mcp2515驅(qū)動(dòng)編寫(xiě):讀寄存器函數(shù)

    迅為RK3568開(kāi)發(fā)板SPI驅(qū)動(dòng)指南-mcp2515驅(qū)動(dòng)編寫(xiě):讀寄存器函數(shù)
    的頭像 發(fā)表于 01-20 14:43 ?1496次閱讀
    迅為RK3568<b class='flag-5'>開(kāi)發(fā)</b>板SPI<b class='flag-5'>驅(qū)動(dòng)</b>指南-mcp2515<b class='flag-5'>驅(qū)動(dòng)</b><b class='flag-5'>編寫(xiě)</b>:讀寄存器函數(shù)