打印
[菜农助学交流]

【sun1986821第二帖】【250活动笔记】【E2PROM小试】

[复制链接]
2656|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
    开写第二贴。如上帖预告,这次介绍I2C和E2PROM通信。

    I2C(Inter-Integrated Circuit)总线是由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备。是微电子通信控制领域广泛采用的一种总线标准。它是同步通信的一种特殊形式,具有接口线少,控制方式简单,器件封装形式小,通信速率较高等优点。


     以下是I2C的一些特征:


       1、只要求两条总线线路:一条串行数据线SDA,一条串行时钟线SCL;

  2、每个连接到总线的器件都可以通过唯一的地址和一直存在的简单的主机/从机关系软件设定地址,主机可以作为主机发送器或主机接收器;

  3、它是一个真正的多主机总线,如果两个或更多主机同时初始化,数据传输可以通过冲突检测和仲裁防止数据被破坏;

  4、串行的8 位双向数据传输位速率在标准模式下可达100kbit/s,快速模式下可达400kbit/s,高速模式下可达3.4Mbit/s;

  5、连接到相同总线的IC 数量只受到总线的最大电容400pF 限制。

    以上介绍参考百度百科。

    本次实验用的是250板载的24C16,容量是256*8个字节。即8个页,每页有8个位所寻址的地址。由于A2-A0端口不需要也无法连接 所以一个I2C总线上只能连接一片24C16。

    上图是4种容量的E2PROM的高3位地址描述方式。

   

    上图为单字节写入的操作 Device Address的最低位为0为写入,1为读出。Device Address的3-1位为数据寻址的高3位,后面的Word Address为低8位。



    上图为读取指定地址的数据的一帧命令

    下面是实际程序,从例程修改而来。

#include <stdio.h>
#include "NUC1xx.h"
#include "Driver\DrvSYS.h"
#include "Driver\DrvGPIO.h"
#include "EEPROM_24LC64.h"
#include "Driver\DrvI2C.h"
#include "Driver\DrvUART.h"

int main(void)
{
uint32_t addr = 0x00000010;
uint8_t datain[] = "OK";
uint8_t i, i2cdata;
STR_UART_T sParam;
/* Unlock the protected registers */
UNLOCKREG();
/* Enable the 12MHz oscillator oscillation */
DrvSYS_SetOscCtrl(E_SYS_XTL12M, 1);

/* Waiting for 12M Xtal stalble */
DrvSYS_Delay(5000);

/* HCLK clock source. 0: external 12MHz; 4:internal 22MHz RC oscillator */
DrvSYS_SelectHCLKSource(0);
/* Set UART I/O */
DrvGPIO_InitFunction(E_FUNC_UART0);

/* Select UART Clock Source From 12MHz */
DrvSYS_SelectIPClockSource(E_SYS_UART_CLKSRC, 0);
/*lock the protected registers */
LOCKREG();

DrvSYS_SetClockDivider(E_SYS_HCLK_DIV, 0); /* HCLK clock frequency = HCLK clock source / (HCLK_N + 1) */

/* UART Setting */
sParam.u32BaudRate = 9600;
sParam.u8cDataBits = DRVUART_DATABITS_8;
sParam.u8cStopBits = DRVUART_STOPBITS_1;
sParam.u8cParity = DRVUART_PARITY_NONE;
sParam.u8cRxTriggerLevel= DRVUART_FIFO_1BYTES;

/* Set UART Configuration */
DrvUART_Open(UART_PORT0, &sParam);
DrvGPIO_InitFunction(E_FUNC_I2C1);
for(i=0; i<2; i++)
{
Write_24LC64(addr,datain[i]);
i2cdata= Read_24LC64(addr);
_DRVUART_SENDBYTE (UART_PORT0, i2cdata);
}

while(1);

}



下面是EEPROM_24LC64.c的函数

#include "NUC1xx.h"
#include "Driver\DrvGPIO.h"
#include "Driver\DrvI2C.h"
#include "Driver\DrvSYS.h"
#include "EEPROM_24LC64.h"

void Write_24LC64(uint32_t address,uint8_t data )
{
uint32_t i;
SystemCoreClock = DrvSYS_GetHCLKFreq();
//Open I2C1 and set clock = 50Kbps
DrvI2C_Open(I2C_PORT1, 50000);

//send i2c start
DrvI2C_Ctrl(I2C_PORT1, 1, 0, 0, 0); //set start
while (I2C1->CON.SI == 0); //poll si flag

//send writer command
I2C1->DATA = (address>>7) & 0x0E | 0XA0;
//send writer command
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 0); //clr si flag
while( I2C1->CON.SI == 0 ); //poll si flag

//send address
I2C1->DATA = address&0XFF;
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1); //clr si and set ack
while( I2C1->CON.SI == 0 ); //poll si flag

//send data
I2C1->DATA = data; //write data to
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1); //clr si and set ack
while( I2C1->CON.SI == 0 ); //poll si flag

//send i2c stop
DrvI2C_Ctrl(I2C_PORT1, 0, 1, 1, 0); //send stop
//while( I2C1->CON.SI == 0 );
for(i=0;i<60;i++);
DrvI2C_Close(I2C_PORT1);

for(i=0;i<6000;i++);
for(i=0;i<6000;i++);
}

uint8_t Read_24LC64(uint32_t address)
{
uint8_t TEMP;
//Open I2C1 and set clock = 50Kbps
SystemCoreClock = DrvSYS_GetHCLKFreq();
DrvI2C_Open(I2C_PORT1, 50000);

//send i2c start
DrvI2C_Ctrl(I2C_PORT1, 1, 0, 1, 0); //set start
while (I2C1->CON.SI == 0); //poll si flag

//send writer command
I2C1->DATA = (address>>7) & 0x0E | 0XA0;
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 0); //clr si
while( I2C1->CON.SI == 0 ); //poll si flag

//send address
I2C1->DATA = address&0XFF;
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 0); //clr si and set ack
while( I2C1->CON.SI == 0 ); //poll si flag

//send start flag
DrvI2C_Ctrl(I2C_PORT1, 1, 0, 1, 0); //clr si and send start
while( I2C1->CON.SI == 0 ); //poll si flag

//send read command
I2C1->DATA = (address>>7) & 0x0E | 0XA1;
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1); //clr si
while( I2C1->CON.SI == 0 ); //poll si flag

//resive data
I2C1->DATA = 0XFF;
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 0); //clr si
while( I2C1->CON.SI == 0 ); //poll si flag
TEMP= I2C1->DATA;

//send i2c stop
DrvI2C_Ctrl(I2C_PORT1, 0, 1, 1, 0); //clr si and set stop
DrvI2C_Close(I2C_PORT1);

return TEMP;
}


    总共的功能是把一个“OK”字符串写入E2PROM,再读出装入另一个字符数组,用串口打印出来。

    下面是效果图


    好的,先写到这,主要的流程就是跟上面几张图的思想是一样的。下次介绍下CoOS吧,本人比较喜欢他们的开发环境CoIDE。




003.jpg (11.61 KB )

003.jpg

相关帖子

沙发
sun1986821|  楼主 | 2011-10-31 22:22 | 只看该作者
不留沙发!:lol

使用特权

评论回复
板凳
hotpower| | 2011-11-1 11:11 | 只看该作者
感觉没什么创意呀。

使用特权

评论回复
地板
sun1986821|  楼主 | 2011-11-1 19:53 | 只看该作者
嗯,这个主要就是介绍下这个的原理和最简单的实现方法。之前对I2C一知半解的,这个算是一个学习笔记吧。 3# hotpower

使用特权

评论回复
5
lixupengarm| | 2011-11-1 21:49 | 只看该作者
:D学习!!

使用特权

评论回复
6
hotpower| | 2011-11-2 18:14 | 只看该作者
实际新唐这个iic的例程不好,没体现一点iic的协议。

使用特权

评论回复
7
sun1986821|  楼主 | 2011-11-3 17:17 | 只看该作者
关于IIC我也是初学啊。。。所以就就着学了 6# hotpower

使用特权

评论回复
8
hotpower| | 2011-11-3 22:51 | 只看该作者
关于IIC我也是初学啊。。。所以就就着学了  6# hotpower
sun1986821 发表于 2011-11-3 17:17


要学习就要学习协议。
实际I2C硬件每步都会产生一个状态,故用状态机比较好。
特别是多机通讯时。

你这样的例程真的不好~~~

使用特权

评论回复
9
sun1986821|  楼主 | 2011-11-4 16:10 | 只看该作者
恩 后来我看真正IIC里面的例程 貌似是状态机的模式。稍微理解了一点 8# hotpower

使用特权

评论回复
10
hotpower| | 2011-11-4 20:20 | 只看该作者
对了,所以我说这个例程极为不好。iic不是这样控制的。而且新唐的iic是标准的,故不要这样做。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

21

帖子

1

粉丝