打印
[活动专区]

赛元易码魔盒体验——12测试拓展板的TWI-EEPROM

[复制链接]
789|12
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
这节我们来使用SC95F8617的TWI(也可以说是IIC)来实现对EEPROM的读写操作,先来看一下设计的原理图,EEPROM接到了P0.4和P0.5,即是USCI0-TWI上,这样我们通过操作TWI(就是IIC)来实现对EEPROM的读写。

使用特权

评论回复

相关帖子

沙发
一路向北lm|  楼主 | 2020-7-18 10:51 | 只看该作者
先使用魔盒打开USCI0的TWI功能,地址配置为0xa0,中断接收允许。同时也把串口UART0打开,TIM3定时器打开,LED指示灯打开,具体配置如下。

使用特权

评论回复
板凳
一路向北lm|  楼主 | 2020-7-18 10:52 | 只看该作者
生成工程,大家注意,前方高能,需要添加很多代码,第一步就是添加LED的翻转操作,用来指示TIM3的定时状态。
#define  LED_PIN      GPIO_PIN_4
#define  LED_PORT     GPIO2
#define  LED_OFF      GPIO_WriteHigh(LED_PORT, LED_PIN)
#define  LED_ON       GPIO_WriteLow(LED_PORT, LED_PIN)
#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中调用。
void Timer3Interrupt()                interrupt 13
{
/*<UserCodeStart>*/
static unsigned int count = 0;
    TXINX = 0x03;   //选择定时器T3
          TFX = 0;        //溢出清零
        count++;
        if(count == 1000)
        {
          count = 0;
                timeflag = 1;
          LED_TOGGLE;       
        }
/*<UserCodeEnd>*/
    /*Timer3_it write here*/               
}


使用特权

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

/*<UserCodeEnd>*/
    /*UART0_it write here*/               
}


使用特权

评论回复
6
一路向北lm|  楼主 | 2020-7-18 10:53 | 只看该作者
第三步添加串口的发送数据函数和接收数据函数,这里暂时不需要接收数据,因此只添加了发送数据函数,包括发送一个字节数据和发送字符串数据。发送函数需要检测标志位与中断建立联系。
extern unsigned char UartSendFlag;
extern unsigned char UartReceiveFlag;
/*****************************************************
*函数名称:Uart_Send_Byte(unsigned char byte)
*函数功能:串口发送一个字节函数
*入口参数:unsigned char byte
*出口参数:void
*****************************************************/
void Uart_Send_Byte(unsigned char byte)
{
  
          SBUF = byte;
                while(!UartSendFlag);
          UartSendFlag = 0;
  
}
/*****************************************************
*函数名称:void Uart_Send_String(unsigned char *str)
*函数功能:串口发送字符串函数
*入口参数:unsigned char *str
*出口参数:void
*****************************************************/
void Uart_Send_String(unsigned char *str)
{
    while(*str)
                {
                        Uart_Send_Byte(*str);
                        str++;
                }
}


使用特权

评论回复
7
一路向北lm|  楼主 | 2020-7-18 10:54 | 只看该作者
调试完串口、定时器之后,即可以开始USCI0-TWI(IIC)的调试。添加一个供USCI0-TWI延时需要的函数,具体如下:
/**************************************************
*函数名称:USCI0_TWI_Delay
*函数功能:TWI延时函数
*入口参数:unsigned int some_times
*出口参数:void
**************************************************/
void USCI0_TWI_Delay(unsigned int some_times)
{
         uint16_t j=some_times;   
   while(j)
   {
     j--;
   }
}


使用特权

评论回复
8
一路向北lm|  楼主 | 2020-7-18 10:54 | 只看该作者
第五步,为了USCI0-TWI的可以正常的收发数据,需要完善对应中断服务函数,也是通过中断标志位的形式来和函数之间进行数据交互。
void USCI0Interrupt()                        interrupt 7                
{
/*<UserCodeStart>*/
  if(US0CON0&0x40)
        {
                US0CON0 &= 0xbf;  //中断清零
                TWI0Flag = 1;
        }       
/*<UserCodeEnd>*/
    /*USCI0_it write here*/               
}


使用特权

评论回复
9
一路向北lm|  楼主 | 2020-7-18 10:55 | 只看该作者
第六步,有了中断标志位和对应的延时函数,我们需要修改USCI0-TWI的开始、停止、发送数据和接收函数,使该部分函数执行更加有效。
/**************************************************
*函数名称:void USCI0_TWI_Start(void)
*函数功能:USCI0 TWI 起始位
*入口参数:void
*出口参数:void
**************************************************/
void USCI0_TWI_Start(void)
{
        static uint16_t i=10000;
        US0CON1 |= 0x20;
  while(!TWI0Flag)
        {
                i--;
                if(i==0) break;       
        }
  TWI0Flag = 0;
        USCI0_TWI_Delay(200);        
}

/**************************************************
*函数名称:void USCI0_TWI_MasterModeStop(void)
*函数功能:USCI0 TWI主机模式停止位
*入口参数:void
*出口参数:void
**************************************************/
void USCI0_TWI_MasterModeStop(void)
{
        US0CON1 |= 0x10;
    USCI0_TWI_Delay(1300);       
}
/*****************************************************
*函数名称:void USCI0_TWI_SendData(uint8_t Data)
*函数功能:TWI发送数据
*入口参数:Data                发送的数据
*出口参数:void
*****************************************************/
void USCI0_TWI_SendData(uint8_t Data)
{
          static uint16_t i=10000;
          US0CON3 = Data;       
                while(!TWI0Flag)
                {
                        i--;
                        if(i==0) break;       
                }
}

/*****************************************************
*函数名称:uint8_t USCI0_TWI_SendData(void)
*函数功能:获得US0CON3中的值
*入口参数:void
*出口参数:uint8_t       
*****************************************************/
uint8_t USCI0_TWI_ReceiveData(void)
{       
        static uint16_t i=10000;
        uint8_t ReceiveByte=0;       
        while(!TWI0Flag)
        {
                i--;
                if(i==0) break;       
        }
  TWI0Flag = 0;
        ReceiveByte = US0CON3;
  return ReceiveByte;
}


使用特权

评论回复
10
一路向北lm|  楼主 | 2020-7-18 10:55 | 只看该作者
第七步,添加应答函数、非应答函数、等待应答函数,这些魔盒默认没有生成。
/*******************************************************************************
* Function Name  : USCI0_TWI_WaitAck
* Description    : None
* Input          : None
* Output         : None
* Return         : 返回为:=1有ACK,=0无ACK
* Attention                 : None
*******************************************************************************/
unsigned char USCI0_TWI_WaitAck(void)        
{

        if(~(US0CON0&0x80))
        {

                return 0;
        }

        return 1;

}
/*******************************************************************************
* Function Name  : USCI0_TWI_NoAck
* Description    : None
* Input          : None
* Output         : None
* Return         : None
* Attention                 : None
*******************************************************************************/
void USCI0_TWI_NoAck(void)
{       
        US0CON0 &= ~(0x08);
  USCI0_TWI_Delay(1300);
}
/*******************************************************************************
* Function Name  : USCI0_TWI_Ack
* Description    : None
* Input          : None
* Output         : None
* Return         : None
* Attention                 : None
*******************************************************************************/
void USCI0_TWI_Ack(void)
{       
        US0CON0 |= 0x08;
        USCI0_TWI_Delay(1300);
}


使用特权

评论回复
11
一路向北lm|  楼主 | 2020-7-18 10:55 | 只看该作者
第八步,有了这些我们就可以编写EEPROM的驱动啦,以24C02为例,编写的读写数据函数如下:
//在 EEPROM 指定地址写入一个数据
//unsigned char WriteAddr :写入数据的目的地址
//unsigned char DataToWrite:要写入的数据
void EEPROM_WriteOneByte(unsigned char WriteAddr,unsigned char DataToWrite)
{
          USCI0_TWI_Start();
      USCI0_TWI_SendData(0XA0); //发送器件地址 0XA0,写数据
          USCI0_TWI_WaitAck();
          USCI0_TWI_Delay(1300);
       
    USCI0_TWI_SendData(WriteAddr); //发送低地址
    USCI0_TWI_WaitAck();
        USCI0_TWI_Delay(1300);
    USCI0_TWI_SendData(DataToWrite); //发送字节
    USCI0_TWI_WaitAck();
        USCI0_TWI_Delay(1300);
    USCI0_TWI_MasterModeStop(); //产生一个停止条件
}
//在 AT24CXX 指定地址读出一个数据
//ReadAddr:开始读数的地址
//返回值 :读到的数据
unsigned char EEPROM_ReadOneByte(unsigned char ReadAddr)
{
    unsigned char temp=0;
    USCI0_TWI_Start();
    USCI0_TWI_SendData(0XA0);  //发送器件地址 0XA0,写数据
    USCI0_TWI_WaitAck();
        USCI0_TWI_Delay(1300);
       
    USCI0_TWI_SendData(ReadAddr); //发送地址
    USCI0_TWI_WaitAck();
        USCI0_TWI_Delay(1300);
       
    USCI0_TWI_Start();
    USCI0_TWI_SendData(0XA1); //进入接收模式
    USCI0_TWI_NoAck();
        USCI0_TWI_Delay(1300);
       
    temp=USCI0_TWI_ReceiveData();
    USCI0_TWI_MasterModeStop(); //产生一个停止条件
    return temp;
}


使用特权

评论回复
12
一路向北lm|  楼主 | 2020-7-18 10:56 | 只看该作者
第九步,到里激动人心的测试部分了,哈哈哈,究竟能不能准确的对24C02进行正确的读写呢,先来写一个测试程序,代码如下,供大家参考。
void main(void)
{       
/*<UserCodeStart>*/

/*<UserCodeEnd>*/
    /*** MCU初始化函数 ***/
  SC_Init();
        while(1)
        {
        if(timeflag == 1)
        {          
                timeflag = 0;
               
       
                        EEPROM_WriteOneByte(i,i);
                  USCI0_TWI_Delay(2500);
                  USCI0_TWI_Delay(2500);
                 
                        temper = EEPROM_ReadOneByte(i);
                        Uart_Send_Byte(temper);
                       
            i++;
        }
       
        }   
}


使用特权

评论回复
13
一路向北lm|  楼主 | 2020-7-18 10:56 | 只看该作者
我这边测试很顺利,一切正常,大家注意一下,在写入数据之后最好多给些延时,再来读取数据,这样能保证写入数据的可靠性。

使用特权

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

本版积分规则

277

主题

3805

帖子

76

粉丝