[活动专区] 赛元易码魔盒体验——12测试拓展板的TWI-EEPROM

[复制链接]
1066|12
 楼主| 一路向北lm 发表于 2020-7-18 10:51 | 显示全部楼层 |阅读模式
这节我们来使用SC95F8617的TWI(也可以说是IIC)来实现对EEPROM的读写操作,先来看一下设计的原理图,EEPROM接到了P0.4和P0.5,即是USCI0-TWI上,这样我们通过操作TWI(就是IIC)来实现对EEPROM的读写。
2435f12639d294ae.png
826415f1263a4a84ec.png

 楼主| 一路向北lm 发表于 2020-7-18 10:51 | 显示全部楼层
先使用魔盒打开USCI0的TWI功能,地址配置为0xa0,中断接收允许。同时也把串口UART0打开,TIM3定时器打开,LED指示灯打开,具体配置如下。
432285f1263bd5dfae.png
 楼主| 一路向北lm 发表于 2020-7-18 10:52 | 显示全部楼层
生成工程,大家注意,前方高能,需要添加很多代码,第一步就是添加LED的翻转操作,用来指示TIM3的定时状态。
  1. #define  LED_PIN      GPIO_PIN_4
  2. #define  LED_PORT     GPIO2
  3. #define  LED_OFF      GPIO_WriteHigh(LED_PORT, LED_PIN)
  4. #define  LED_ON       GPIO_WriteLow(LED_PORT, LED_PIN)
  5. #define  LED_TOGGLE   GPIO_ReadPin(LED_PORT,LED_PIN)? GPIO_WriteLow(LED_PORT, LED_PIN): GPIO_WriteHigh(LED_PORT, LED_PIN)


 楼主| 一路向北lm 发表于 2020-7-18 10:52 | 显示全部楼层
第二步添加定时器的中断处理函数,每隔1S翻转LED作为指示,将标志位置1,此标志位在main.c中调用。
  1. void Timer3Interrupt()                interrupt 13
  2. {
  3. /*<UserCodeStart>*/
  4. static unsigned int count = 0;
  5.     TXINX = 0x03;   //选择定时器T3
  6.           TFX = 0;        //溢出清零
  7.         count++;
  8.         if(count == 1000)
  9.         {
  10.           count = 0;
  11.                 timeflag = 1;
  12.           LED_TOGGLE;       
  13.         }
  14. /*<UserCodeEnd>*/
  15.     /*Timer3_it write here*/               
  16. }


 楼主| 一路向北lm 发表于 2020-7-18 10:53 | 显示全部楼层
第三步添加串口的中断处理函数,主要用来收发数据,所以说要实现SC95F的一些功能,基本上都离不开中断。在串口接收到数据或者发送完数据都会将对应的标志位置1,改标志位需要自己定义。
  1. void UART0Interrupt()                interrupt 4               
  2. {
  3. /*<UserCodeStart>*/
  4.           if(TI)
  5.         {
  6.             TI = 0;        
  7.             UartSendFlag = 1;               
  8.         }
  9.         if(RI)
  10.         {
  11.             RI = 0;        
  12.             UartReceiveFlag = 1;
  13.         }        

  14. /*<UserCodeEnd>*/
  15.     /*UART0_it write here*/               
  16. }


 楼主| 一路向北lm 发表于 2020-7-18 10:53 | 显示全部楼层
第三步添加串口的发送数据函数和接收数据函数,这里暂时不需要接收数据,因此只添加了发送数据函数,包括发送一个字节数据和发送字符串数据。发送函数需要检测标志位与中断建立联系。
  1. extern unsigned char UartSendFlag;
  2. extern unsigned char UartReceiveFlag;
  3. /*****************************************************
  4. *函数名称:Uart_Send_Byte(unsigned char byte)
  5. *函数功能:串口发送一个字节函数
  6. *入口参数:unsigned char byte
  7. *出口参数:void
  8. *****************************************************/
  9. void Uart_Send_Byte(unsigned char byte)
  10. {
  11.   
  12.           SBUF = byte;
  13.                 while(!UartSendFlag);
  14.           UartSendFlag = 0;
  15.   
  16. }
  17. /*****************************************************
  18. *函数名称:void Uart_Send_String(unsigned char *str)
  19. *函数功能:串口发送字符串函数
  20. *入口参数:unsigned char *str
  21. *出口参数:void
  22. *****************************************************/
  23. void Uart_Send_String(unsigned char *str)
  24. {
  25.     while(*str)
  26.                 {
  27.                         Uart_Send_Byte(*str);
  28.                         str++;
  29.                 }
  30. }


 楼主| 一路向北lm 发表于 2020-7-18 10:54 | 显示全部楼层
调试完串口、定时器之后,即可以开始USCI0-TWI(IIC)的调试。添加一个供USCI0-TWI延时需要的函数,具体如下:
  1. /**************************************************
  2. *函数名称:USCI0_TWI_Delay
  3. *函数功能:TWI延时函数
  4. *入口参数:unsigned int some_times
  5. *出口参数:void
  6. **************************************************/
  7. void USCI0_TWI_Delay(unsigned int some_times)
  8. {
  9.          uint16_t j=some_times;   
  10.    while(j)
  11.    {
  12.      j--;
  13.    }
  14. }


 楼主| 一路向北lm 发表于 2020-7-18 10:54 | 显示全部楼层
第五步,为了USCI0-TWI的可以正常的收发数据,需要完善对应中断服务函数,也是通过中断标志位的形式来和函数之间进行数据交互。
  1. void USCI0Interrupt()                        interrupt 7               
  2. {
  3. /*<UserCodeStart>*/
  4.   if(US0CON0&0x40)
  5.         {
  6.                 US0CON0 &= 0xbf;  //中断清零
  7.                 TWI0Flag = 1;
  8.         }       
  9. /*<UserCodeEnd>*/
  10.     /*USCI0_it write here*/               
  11. }


 楼主| 一路向北lm 发表于 2020-7-18 10:55 | 显示全部楼层
第六步,有了中断标志位和对应的延时函数,我们需要修改USCI0-TWI的开始、停止、发送数据和接收函数,使该部分函数执行更加有效。
  1. /**************************************************
  2. *函数名称:void USCI0_TWI_Start(void)
  3. *函数功能:USCI0 TWI 起始位
  4. *入口参数:void
  5. *出口参数:void
  6. **************************************************/
  7. void USCI0_TWI_Start(void)
  8. {
  9.         static uint16_t i=10000;
  10.         US0CON1 |= 0x20;
  11.   while(!TWI0Flag)
  12.         {
  13.                 i--;
  14.                 if(i==0) break;       
  15.         }
  16.   TWI0Flag = 0;
  17.         USCI0_TWI_Delay(200);        
  18. }

  19. /**************************************************
  20. *函数名称:void USCI0_TWI_MasterModeStop(void)
  21. *函数功能:USCI0 TWI主机模式停止位
  22. *入口参数:void
  23. *出口参数:void
  24. **************************************************/
  25. void USCI0_TWI_MasterModeStop(void)
  26. {
  27.         US0CON1 |= 0x10;
  28.     USCI0_TWI_Delay(1300);       
  29. }
  30. /*****************************************************
  31. *函数名称:void USCI0_TWI_SendData(uint8_t Data)
  32. *函数功能:TWI发送数据
  33. *入口参数:Data                发送的数据
  34. *出口参数:void
  35. *****************************************************/
  36. void USCI0_TWI_SendData(uint8_t Data)
  37. {
  38.           static uint16_t i=10000;
  39.           US0CON3 = Data;       
  40.                 while(!TWI0Flag)
  41.                 {
  42.                         i--;
  43.                         if(i==0) break;       
  44.                 }
  45. }

  46. /*****************************************************
  47. *函数名称:uint8_t USCI0_TWI_SendData(void)
  48. *函数功能:获得US0CON3中的值
  49. *入口参数:void
  50. *出口参数:uint8_t       
  51. *****************************************************/
  52. uint8_t USCI0_TWI_ReceiveData(void)
  53. {       
  54.         static uint16_t i=10000;
  55.         uint8_t ReceiveByte=0;       
  56.         while(!TWI0Flag)
  57.         {
  58.                 i--;
  59.                 if(i==0) break;       
  60.         }
  61.   TWI0Flag = 0;
  62.         ReceiveByte = US0CON3;
  63.   return ReceiveByte;
  64. }


 楼主| 一路向北lm 发表于 2020-7-18 10:55 | 显示全部楼层
第七步,添加应答函数、非应答函数、等待应答函数,这些魔盒默认没有生成。
  1. /*******************************************************************************
  2. * Function Name  : USCI0_TWI_WaitAck
  3. * Description    : None
  4. * Input          : None
  5. * Output         : None
  6. * Return         : 返回为:=1有ACK,=0无ACK
  7. * Attention                 : None
  8. *******************************************************************************/
  9. unsigned char USCI0_TWI_WaitAck(void)        
  10. {

  11.         if(~(US0CON0&0x80))
  12.         {

  13.                 return 0;
  14.         }

  15.         return 1;

  16. }
  17. /*******************************************************************************
  18. * Function Name  : USCI0_TWI_NoAck
  19. * Description    : None
  20. * Input          : None
  21. * Output         : None
  22. * Return         : None
  23. * Attention                 : None
  24. *******************************************************************************/
  25. void USCI0_TWI_NoAck(void)
  26. {       
  27.         US0CON0 &= ~(0x08);
  28.   USCI0_TWI_Delay(1300);
  29. }
  30. /*******************************************************************************
  31. * Function Name  : USCI0_TWI_Ack
  32. * Description    : None
  33. * Input          : None
  34. * Output         : None
  35. * Return         : None
  36. * Attention                 : None
  37. *******************************************************************************/
  38. void USCI0_TWI_Ack(void)
  39. {       
  40.         US0CON0 |= 0x08;
  41.         USCI0_TWI_Delay(1300);
  42. }


 楼主| 一路向北lm 发表于 2020-7-18 10:55 | 显示全部楼层
第八步,有了这些我们就可以编写EEPROM的驱动啦,以24C02为例,编写的读写数据函数如下:
  1. //在 EEPROM 指定地址写入一个数据
  2. //unsigned char WriteAddr :写入数据的目的地址
  3. //unsigned char DataToWrite:要写入的数据
  4. void EEPROM_WriteOneByte(unsigned char WriteAddr,unsigned char DataToWrite)
  5. {
  6.           USCI0_TWI_Start();
  7.       USCI0_TWI_SendData(0XA0); //发送器件地址 0XA0,写数据
  8.           USCI0_TWI_WaitAck();
  9.           USCI0_TWI_Delay(1300);
  10.        
  11.     USCI0_TWI_SendData(WriteAddr); //发送低地址
  12.     USCI0_TWI_WaitAck();
  13.         USCI0_TWI_Delay(1300);
  14.     USCI0_TWI_SendData(DataToWrite); //发送字节
  15.     USCI0_TWI_WaitAck();
  16.         USCI0_TWI_Delay(1300);
  17.     USCI0_TWI_MasterModeStop(); //产生一个停止条件
  18. }
  19. //在 AT24CXX 指定地址读出一个数据
  20. //ReadAddr:开始读数的地址
  21. //返回值 :读到的数据
  22. unsigned char EEPROM_ReadOneByte(unsigned char ReadAddr)
  23. {
  24.     unsigned char temp=0;
  25.     USCI0_TWI_Start();
  26.     USCI0_TWI_SendData(0XA0);  //发送器件地址 0XA0,写数据
  27.     USCI0_TWI_WaitAck();
  28.         USCI0_TWI_Delay(1300);
  29.        
  30.     USCI0_TWI_SendData(ReadAddr); //发送地址
  31.     USCI0_TWI_WaitAck();
  32.         USCI0_TWI_Delay(1300);
  33.        
  34.     USCI0_TWI_Start();
  35.     USCI0_TWI_SendData(0XA1); //进入接收模式
  36.     USCI0_TWI_NoAck();
  37.         USCI0_TWI_Delay(1300);
  38.        
  39.     temp=USCI0_TWI_ReceiveData();
  40.     USCI0_TWI_MasterModeStop(); //产生一个停止条件
  41.     return temp;
  42. }


 楼主| 一路向北lm 发表于 2020-7-18 10:56 | 显示全部楼层
第九步,到里激动人心的测试部分了,哈哈哈,究竟能不能准确的对24C02进行正确的读写呢,先来写一个测试程序,代码如下,供大家参考。
  1. void main(void)
  2. {       
  3. /*<UserCodeStart>*/

  4. /*<UserCodeEnd>*/
  5.     /*** MCU初始化函数 ***/
  6.   SC_Init();
  7.         while(1)
  8.         {
  9.         if(timeflag == 1)
  10.         {          
  11.                 timeflag = 0;
  12.                
  13.        
  14.                         EEPROM_WriteOneByte(i,i);
  15.                   USCI0_TWI_Delay(2500);
  16.                   USCI0_TWI_Delay(2500);
  17.                  
  18.                         temper = EEPROM_ReadOneByte(i);
  19.                         Uart_Send_Byte(temper);
  20.                        
  21.             i++;
  22.         }
  23.        
  24.         }   
  25. }


 楼主| 一路向北lm 发表于 2020-7-18 10:56 | 显示全部楼层
我这边测试很顺利,一切正常,大家注意一下,在写入数据之后最好多给些延时,再来读取数据,这样能保证写入数据的可靠性。
916385f1264e40b80f.png
您需要登录后才可以回帖 登录 | 注册

本版积分规则

293

主题

3837

帖子

81

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