[菜农助学交流] 【sun1986821第二帖】【250活动笔记】【E2PROM小试】

[复制链接]
3272|9
 楼主| sun1986821 发表于 2011-10-31 22:21 | 显示全部楼层 |阅读模式
    开写第二贴。如上帖预告,这次介绍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位。



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

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

  1. #include <stdio.h>
  2. #include "NUC1xx.h"
  3. #include "Driver\DrvSYS.h"
  4. #include "Driver\DrvGPIO.h"
  5. #include "EEPROM_24LC64.h"
  6. #include "Driver\DrvI2C.h"
  7. #include "Driver\DrvUART.h"

  8. int main(void)
  9. {
  10. uint32_t addr = 0x00000010;
  11. uint8_t datain[] = "OK";
  12. uint8_t i, i2cdata;
  13. STR_UART_T sParam;
  14. /* Unlock the protected registers */
  15. UNLOCKREG();
  16. /* Enable the 12MHz oscillator oscillation */
  17. DrvSYS_SetOscCtrl(E_SYS_XTL12M, 1);

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

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

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

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

  29. /* UART Setting */
  30. sParam.u32BaudRate = 9600;
  31. sParam.u8cDataBits = DRVUART_DATABITS_8;
  32. sParam.u8cStopBits = DRVUART_STOPBITS_1;
  33. sParam.u8cParity = DRVUART_PARITY_NONE;
  34. sParam.u8cRxTriggerLevel= DRVUART_FIFO_1BYTES;

  35. /* Set UART Configuration */
  36. DrvUART_Open(UART_PORT0, &sParam);
  37. DrvGPIO_InitFunction(E_FUNC_I2C1);
  38. for(i=0; i<2; i++)
  39. {
  40. Write_24LC64(addr,datain[i]);
  41. i2cdata= Read_24LC64(addr);
  42. _DRVUART_SENDBYTE (UART_PORT0, i2cdata);
  43. }

  44. while(1);

  45. }



下面是EEPROM_24LC64.c的函数

  1. #include "NUC1xx.h"
  2. #include "Driver\DrvGPIO.h"
  3. #include "Driver\DrvI2C.h"
  4. #include "Driver\DrvSYS.h"
  5. #include "EEPROM_24LC64.h"

  6. void Write_24LC64(uint32_t address,uint8_t data )
  7. {
  8. uint32_t i;
  9. SystemCoreClock = DrvSYS_GetHCLKFreq();
  10. //Open I2C1 and set clock = 50Kbps
  11. DrvI2C_Open(I2C_PORT1, 50000);

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

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

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

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

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

  33. for(i=0;i<6000;i++);
  34. for(i=0;i<6000;i++);
  35. }

  36. uint8_t Read_24LC64(uint32_t address)
  37. {
  38. uint8_t TEMP;
  39. //Open I2C1 and set clock = 50Kbps
  40. SystemCoreClock = DrvSYS_GetHCLKFreq();
  41. DrvI2C_Open(I2C_PORT1, 50000);

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

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

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

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

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

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

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

  68. return TEMP;
  69. }


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

    下面是效果图


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




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
 楼主| sun1986821 发表于 2011-10-31 22:22 | 显示全部楼层
不留沙发!:lol
hotpower 发表于 2011-11-1 11:11 | 显示全部楼层
感觉没什么创意呀。
 楼主| sun1986821 发表于 2011-11-1 19:53 | 显示全部楼层
嗯,这个主要就是介绍下这个的原理和最简单的实现方法。之前对I2C一知半解的,这个算是一个学习笔记吧。 3# hotpower
lixupengarm 发表于 2011-11-1 21:49 | 显示全部楼层
:D学习!!
hotpower 发表于 2011-11-2 18:14 | 显示全部楼层
实际新唐这个iic的例程不好,没体现一点iic的协议。
 楼主| sun1986821 发表于 2011-11-3 17:17 | 显示全部楼层
关于IIC我也是初学啊。。。所以就就着学了 6# hotpower
hotpower 发表于 2011-11-3 22:51 | 显示全部楼层
关于IIC我也是初学啊。。。所以就就着学了  6# hotpower
sun1986821 发表于 2011-11-3 17:17


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

你这样的例程真的不好~~~
 楼主| sun1986821 发表于 2011-11-4 16:10 | 显示全部楼层
恩 后来我看真正IIC里面的例程 貌似是状态机的模式。稍微理解了一点 8# hotpower
hotpower 发表于 2011-11-4 20:20 | 显示全部楼层
对了,所以我说这个例程极为不好。iic不是这样控制的。而且新唐的iic是标准的,故不要这样做。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

21

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部