开写第二贴。如上帖预告,这次介绍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。
|