打印
[DemoCode下载]

MINI51的IIC通信

[复制链接]
766|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
598330983|  楼主 | 2019-4-30 20:17 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
[Mini51][I2C]Master_Slave_communication.zip (468.99 KB)

使用特权

评论回复
沙发
598330983|  楼主 | 2019-4-30 20:18 | 只看该作者
/******************************************************************************
* [url=home.php?mod=space&uid=288409]@file[/url]     main.c
* [url=home.php?mod=space&uid=895143]@version[/url]  V0.10
* $Revision: 4 $
* $Date: 13/10/07 3:56p $
* [url=home.php?mod=space&uid=247401]@brief[/url]    Mini51 Series I2C Driver Sample Code
*
* @note
* Copyright (C) 2013 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include <stdio.h>
#include "Mini51Series.h"

/*---------------------------------------------------------------------------------------------------------*/
/* Global variables                                                                                        */
/*---------------------------------------------------------------------------------------------------------*/

volatile uint8_t g_u8DeviceAddr;
volatile uint8_t g_u8DataLen;
volatile uint8_t rawlenth;
volatile uint8_t g_au8Reg;
volatile uint8_t g_u8EndFlag = 0;
uint8_t *g_au8Buffer;

typedef void (*I2C_FUNC)(uint32_t u32Status);

I2C_FUNC __IO s_I2CHandlerFn = NULL;

/*---------------------------------------------------------------------------------------------------------*/
/*  I2C IRQ Handler                                                                                       */
/*---------------------------------------------------------------------------------------------------------*/
void I2C_IRQHandler(void)
{
    uint32_t u32Status;

    u32Status = I2C_GET_STATUS(I2C);

    if (I2C_GET_TIMEOUT_FLAG(I2C))
    {
        /* Clear I2C Timeout Flag */
        I2C_ClearTimeoutFlag(I2C);                  
    }   
    else
    {
        if (s_I2CHandlerFn != NULL)
            s_I2CHandlerFn(u32Status);
    }
}

/*---------------------------------------------------------------------------------------------------------*/
/*  I2C Rx multi Callback Function                                                                               */
/*---------------------------------------------------------------------------------------------------------*/
void I2C_MasterRx_multi(uint32_t u32Status)
{
    if(u32Status == 0x08)                       /* START has been transmitted and prepare SLA+W */
    {
        I2C_SET_DATA(I2C, (g_u8DeviceAddr << 1));    /* Write SLA+W to Register I2CDAT */
        I2C_SET_CONTROL_REG(I2C, I2C_SI);
    }
    else if(u32Status == 0x18)                  /* SLA+W has been transmitted and ACK has been received */
    {
        I2C_SET_DATA(I2C, g_au8Reg);
        I2C_SET_CONTROL_REG(I2C, I2C_SI);
    }
    else if(u32Status == 0x20)                  /* SLA+W has been transmitted and NACK has been received */
    {
        I2C_SET_CONTROL_REG(I2C, I2C_SI | I2C_STA | I2C_STO);
    }
    else if(u32Status == 0x28)                  /* DATA has been transmitted and ACK has been received */
    {
        if (rawlenth > 0)
                                        I2C_SET_CONTROL_REG(I2C, I2C_SI | I2C_STA);//repeat start
                                else
                                {
                                        I2C_SET_CONTROL_REG(I2C, I2C_SI | I2C_STO);
                                        g_u8EndFlag = 1;
                                }
    }
    else if(u32Status == 0x10)                  /* Repeat START has been transmitted and prepare SLA+R */
    {
        I2C_SET_DATA(I2C, ((g_u8DeviceAddr << 1) | 0x01));   /* Write SLA+R to Register I2CDAT */
        I2C_SET_CONTROL_REG(I2C, I2C_SI);
    }
    else if(u32Status == 0x40)                  /* SLA+R has been transmitted and ACK has been received */
    {
                                if (rawlenth > 1)
                                        I2C_SET_CONTROL_REG(I2C, I2C_SI | I2C_AA);
                                else
                                        I2C_SET_CONTROL_REG(I2C, I2C_SI);
    }
                else if(u32Status == 0x50)                  /* DATA has been received and ACK has been returned */
    {
        g_au8Buffer[g_u8DataLen++] = (unsigned char) I2C_GetData(I2C);
        if (g_u8DataLen < (rawlenth-1))
                                {
                                        I2C_SET_CONTROL_REG(I2C, I2C_SI | I2C_AA);
                                }
                                else
                                {
                                        I2C_SET_CONTROL_REG(I2C, I2C_SI);
                                }
    }
    else if(u32Status == 0x58)                  /* DATA has been received and NACK has been returned */
    {
        g_au8Buffer[g_u8DataLen++] = (unsigned char) I2C_GetData(I2C);
        I2C_SET_CONTROL_REG(I2C, I2C_SI | I2C_STO);
        g_u8EndFlag = 1;
    }
    else
    {
        /* TO DO */
        printf("Status 0x%x is NOT processed\n", u32Status);
    }
}
/*---------------------------------------------------------------------------------------------------------*/
/*  I2C Tx multi Callback Function                                                                               */
/*---------------------------------------------------------------------------------------------------------*/
void I2C_MasterTx_multi(uint32_t u32Status)
{
    if(u32Status == 0x08)                       /* START has been transmitted */
    {
        I2C_SET_DATA(I2C, g_u8DeviceAddr << 1);    /* Write SLA+W to Register I2CDAT */
        I2C_SET_CONTROL_REG(I2C, I2C_SI);
    }
    else if(u32Status == 0x18)                  /* SLA+W has been transmitted and ACK has been received */
    {
        I2C_SET_DATA(I2C, g_au8Reg);
        I2C_SET_CONTROL_REG(I2C, I2C_SI);
    }
    else if(u32Status == 0x20)                  /* SLA+W has been transmitted and NACK has been received */
    {
        I2C_SET_CONTROL_REG(I2C, I2C_SI | I2C_STA | I2C_STO);
    }
    else if(u32Status == 0x28)                  /* DATA has been transmitted and ACK has been received */
    {
        if(g_u8DataLen < rawlenth)
        {
            I2C_SET_DATA(I2C, g_au8Buffer[g_u8DataLen++]);
            I2C_SET_CONTROL_REG(I2C, I2C_SI);
        }
        else
        {
            I2C_SET_CONTROL_REG(I2C, I2C_SI | I2C_STO);
            g_u8EndFlag = 1;
        }
    }
    else
    {
        /* TO DO */
        printf("Status 0x%x is NOT processed\n", u32Status);
    }
}

void SYS_Init(void)
{
    /* Unlock protected registers */
    SYS_UnlockReg();

/*---------------------------------------------------------------------------------------------------------*/
/* Init System Clock                                                                                       */
/*---------------------------------------------------------------------------------------------------------*/

    /* Unlock protected registers */
    SYS_UnlockReg();

    /* Enable external 12MHz XTAL, internal 22.1184MHz */
    CLK->PWRCON |= CLK_PWRCON_XTL12M | CLK_PWRCON_IRC22M_EN_Msk;

    /* Waiting for clock ready */
    CLK_WaitClockReady(CLK_CLKSTATUS_XTL_STB_Msk | CLK_CLKSTATUS_IRC22M_STB_Msk);

    /* Switch HCLK clock source to XTL, STCLK to XTL */
    CLK->CLKSEL0 = CLK_CLKSEL0_STCLK_S_XTAL | CLK_CLKSEL0_HCLK_S_XTAL;

    /* Enable IP clock */        
    CLK->APBCLK = CLK_APBCLK_UART_EN_Msk;
   
    /* Select IP clock source */
    CLK->CLKSEL1 = CLK_CLKSEL1_UART_S_XTAL;

/*---------------------------------------------------------------------------------------------------------*/
/* Init I/O Multi-function                                                                                 */
/*---------------------------------------------------------------------------------------------------------*/
    /* Set P0 multi-function pins for UART RXD and TXD */
    SYS->P0_MFP = SYS_MFP_P01_RXD | SYS_MFP_P00_TXD;
   
    /* Set P3.4 and P3.5 for I2C SDA and SCL */
    SYS->P3_MFP = SYS_MFP_P34_SDA | SYS_MFP_P35_SCL;
   
    /* Lock protected registers */
    SYS_LockReg();
   
    /* Update System Core Clock */
    SystemCoreClockUpdate();
}

void UART_Init(void)
{
/*---------------------------------------------------------------------------------------------------------*/
/* Init UART                                                                                               */
/*---------------------------------------------------------------------------------------------------------*/
     /* Reset IP */
    SYS->IPRSTC2 |=  SYS_IPRSTC2_UART_RST_Msk;
    SYS->IPRSTC2 &= ~SYS_IPRSTC2_UART_RST_Msk;
   
    UART->BAUD = UART_BAUD_DIV_X_EN_Msk | UART_BAUD_DIV_X_ONE_Msk | (((__XTAL + (115200/2)) / 115200)-2);   
    UART->LCR = 0x3 | (0x0 << UART_LCR_PBE_Pos) | (0x0 << UART_LCR_NSB_Pos) ;
}

void I2C_Init(void)
{   
    /* Open I2C module and set bus clock */
    I2C_Open(I2C, 100000);
   
     /* Set I2C 4 Slave Addresses */            
    I2C_SetSlaveAddr(I2C, 0, 0x15, 0);   /* Slave Address : 0x15 */
    I2C_SetSlaveAddr(I2C, 1, 0x35, 0);   /* Slave Address : 0x35 */
    I2C_SetSlaveAddr(I2C, 2, 0x55, 0);   /* Slave Address : 0x55 */
    I2C_SetSlaveAddr(I2C, 3, 0x75, 0);   /* Slave Address : 0x75 */

    /* Enable I2C interrupt */
    I2C_EnableInt(I2C);
    NVIC_EnableIRQ(I2C_IRQn);
}

void I2C0_Write_SLAVE_multi(uint8_t slvaddr,uint16_t slvraw,uint8_t slvreg,uint8_t *data)
{
               
                                g_u8DeviceAddr = slvaddr;
                                rawlenth=slvraw;
                                g_au8Reg = slvreg;
                                g_au8Buffer=data;

        g_u8DataLen = 0;
        g_u8EndFlag = 0;

        /* I2C function to write data to slave */
        s_I2CHandlerFn = (I2C_FUNC)I2C_MasterTx_multi;

        /* I2C as master sends START signal */
        I2C_SET_CONTROL_REG(I2C, I2C_STA);

        /* Wait I2C Tx Finish */
        while(g_u8EndFlag == 0);
        g_u8EndFlag = 0;
}

void I2C0_Read_SLAVE_multi(uint8_t slvaddr,uint16_t slvraw,uint8_t slvreg,uint8_t *data)
{
        g_u8DeviceAddr = slvaddr;
                                rawlenth=slvraw;
        g_au8Reg = slvreg ;
                                g_au8Buffer=data;

        g_u8EndFlag = 0;
        g_u8DataLen = 0;
       
        /* I2C function to read data from slave */
        s_I2CHandlerFn = (I2C_FUNC)I2C_MasterRx_multi;
        I2C_SET_CONTROL_REG(I2C, I2C_STA);

        /* Wait I2C Rx Finish */
        while(g_u8EndFlag == 0);
       
}

/*---------------------------------------------------------------------------------------------------------*/
/*  Main Function                                                                                          */
/*---------------------------------------------------------------------------------------------------------*/
int32_t main (void)
{
    uint8_t u8Data[10];
                uint8_t DID,slvreg;
                uint32_t i;
                uint8_t *Buffer;
                uint16_t raw;
               

    /* Init System, IP clock and multi-function I/O */
    SYS_Init();     

    /* Init UART for printf */
    UART_Init();

    /*
        This sample code sets I2C bus clock to 100kHz. Then, accesses EEPROM 24LC64 with Byte Write
        and Byte Read operations, and check if the read data is equal to the programmed data.
    */
   
    printf("+-------------------------------------------------------+\n");
    printf("|    Mini51 I2C Driver Sample Code with EEPROM 24LC64    |\n");
    printf("+-------------------------------------------------------+\n");
   
    /* Init I2C to access EEPROM */
    I2C_Init();
        
    printf("\n");
    printf("Check I2C Slave(I2C0) is running first!\n");
    printf("Press any key to continue.\n");
    getchar();

    /* Access Slave with no address */
    printf("\n");
                               
                DID=0x15;
                slvreg=0x66;
                raw=10;
                Buffer=u8Data;               
                for (i=0;i<raw;i++)
                {
                        Buffer[i]=1<<(i%8);
                }
               
    I2C0_Write_SLAVE_multi(DID,raw,slvreg,Buffer);
                I2C0_Read_SLAVE_multi(DID,raw,slvreg,Buffer);
               
                /* Compare data */
    for (i=0;i<raw;i++)
                {
                        if(Buffer[i] != 1<<(i%8))
                        {
                                        printf("I2C Byte Write/Read Failed, Data 0x%x\n", Buffer[i]);
//                                         while(1);
                        }
                        printf("Master Access Slave Register:0x%X  Data:0x%X Test OK\n", (slvreg+i), Buffer[i]);       
                }
                               
    printf("SLAVE Address test OK.\n");
               
                s_I2CHandlerFn = NULL;
               
    /* Close I2C */
    I2C_Close(I2C);

    return 0;
}



使用特权

评论回复
板凳
598330983|  楼主 | 2019-4-30 20:18 | 只看该作者
/******************************************************************************
* @file     main.c
* @version  V0.10
* $Revision: 4 $
* $Date: 13/10/07 3:56p $
* @brief    Mini51 Series I2C Driver Sample Code
*
* @note
* Copyright (C) 2013 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include <stdio.h>
#include "Mini51Series.h"

uint32_t slave_buff_addr;
uint8_t g_u8SlvData[256];
uint8_t g_au8RxData;
/*---------------------------------------------------------------------------------------------------------*/
/* Global variables                                                                                        */
/*---------------------------------------------------------------------------------------------------------*/
uint8_t g_u8DeviceAddr;
uint8_t g_u8DataLen;

typedef void (*I2C_FUNC)(uint32_t u32Status);

I2C_FUNC __IO s_I2CHandlerFn = NULL;

/*---------------------------------------------------------------------------------------------------------*/
/*  I2C IRQ Handler                                                                                       */
/*---------------------------------------------------------------------------------------------------------*/
void I2C_IRQHandler(void)
{
    uint32_t u32Status;

    u32Status = I2C_GET_STATUS(I2C);

    if (I2C_GET_TIMEOUT_FLAG(I2C))
    {
        /* Clear I2C Timeout Flag */
        I2C_ClearTimeoutFlag(I2C);                  
    }   
    else
    {
        if (s_I2CHandlerFn != NULL)
            s_I2CHandlerFn(u32Status);
    }
}

/*---------------------------------------------------------------------------------------------------------*/
/*  I2C TRx Callback Function                                                                               */
/*---------------------------------------------------------------------------------------------------------*/
void I2C_SlaveTRx(uint32_t u32Status)
{
    if(u32Status == 0x60)                       /* Own SLA+W has been receive; ACK has been return */
    {
        g_u8DataLen = 0;
        I2C_SET_CONTROL_REG(I2C, I2C_SI | I2C_AA);
    }
    else if(u32Status == 0x80)                 /* Previously address with own SLA address
                                                   Data has been received; ACK has been returned*/
    {
        g_au8RxData = (unsigned char) I2C_GET_DATA(I2C);
        g_u8DataLen++;

        if(g_u8DataLen == 1)
        {
            slave_buff_addr = g_au8RxData;
        }
        else
        {
            g_u8SlvData[slave_buff_addr+(g_u8DataLen-2)] = g_au8RxData;
        }
                               
        I2C_SET_CONTROL_REG(I2C, I2C_SI | I2C_AA);
    }
    else if(u32Status == 0xA8)                  /* Own SLA+R has been receive; ACK has been return */
    {
                     I2C_SET_DATA(I2C, g_u8SlvData[slave_buff_addr]);
        I2C_SET_CONTROL_REG(I2C, I2C_SI | I2C_AA);
    }
                else if(u32Status == 0xB8)                 /* Data byte in I2CDAT has been transmitted
                                                   ACK has been received */
    {
        slave_buff_addr=slave_buff_addr+1;
                                I2C_SET_DATA(I2C, g_u8SlvData[slave_buff_addr]);
                                I2C_SET_CONTROL_REG(I2C, I2C_SI | I2C_AA);
    }
    else if(u32Status == 0xC0)                 /* Data byte or last data in I2CDAT has been transmitted
                                                   Not ACK has been received */
    {
        I2C_SET_CONTROL_REG(I2C, I2C_SI | I2C_AA);
    }
    else if(u32Status == 0x88)                 /* Previously addressed with own SLA address; NOT ACK has
                                                   been returned */
    {
        g_u8DataLen = 0;
        I2C_SET_CONTROL_REG(I2C, I2C_SI | I2C_AA);
    }
    else if(u32Status == 0xA0)                 /* A STOP or repeated START has been received while still
                                                   addressed as Slave/Receiver*/
    {
        g_u8DataLen = 0;
        I2C_SET_CONTROL_REG(I2C, I2C_SI | I2C_AA);
    }
    else
    {
        /* TO DO */
        printf("Status 0x%x is NOT processed\n", u32Status);
    }
}

void SYS_Init(void)
{
    /* Unlock protected registers */
    SYS_UnlockReg();

/*---------------------------------------------------------------------------------------------------------*/
/* Init System Clock                                                                                       */
/*---------------------------------------------------------------------------------------------------------*/

    /* Unlock protected registers */
    SYS_UnlockReg();

    /* Enable external 12MHz XTAL, internal 22.1184MHz */
    CLK->PWRCON |= CLK_PWRCON_XTL12M | CLK_PWRCON_IRC22M_EN_Msk;

    /* Waiting for clock ready */
    CLK_WaitClockReady(CLK_CLKSTATUS_XTL_STB_Msk | CLK_CLKSTATUS_IRC22M_STB_Msk);

    /* Switch HCLK clock source to XTL, STCLK to XTL */
    CLK->CLKSEL0 = CLK_CLKSEL0_STCLK_S_XTAL | CLK_CLKSEL0_HCLK_S_XTAL;

    /* Enable IP clock */        
    CLK->APBCLK = CLK_APBCLK_UART_EN_Msk;
   
    /* Select IP clock source */
    CLK->CLKSEL1 = CLK_CLKSEL1_UART_S_XTAL;

/*---------------------------------------------------------------------------------------------------------*/
/* Init I/O Multi-function                                                                                 */
/*---------------------------------------------------------------------------------------------------------*/
    /* Set P0 multi-function pins for UART RXD and TXD */
    SYS->P0_MFP = SYS_MFP_P01_RXD | SYS_MFP_P00_TXD;
   
    /* Set P3.4 and P3.5 for I2C SDA and SCL */
    SYS->P3_MFP = SYS_MFP_P34_SDA | SYS_MFP_P35_SCL;
   
    /* Lock protected registers */
    SYS_LockReg();
   
    /* Update System Core Clock */
    SystemCoreClockUpdate();
}

void UART_Init(void)
{
/*---------------------------------------------------------------------------------------------------------*/
/* Init UART                                                                                               */
/*---------------------------------------------------------------------------------------------------------*/
     /* Reset IP */
    SYS->IPRSTC2 |=  SYS_IPRSTC2_UART_RST_Msk;
    SYS->IPRSTC2 &= ~SYS_IPRSTC2_UART_RST_Msk;
   
    UART->BAUD = UART_BAUD_DIV_X_EN_Msk | UART_BAUD_DIV_X_ONE_Msk | (((__XTAL + (115200/2)) / 115200)-2);   
    UART->LCR = 0x3 | (0x0 << UART_LCR_PBE_Pos) | (0x0 << UART_LCR_NSB_Pos) ;
}

void I2C_Init(void)
{   
    /* Open I2C module and set bus clock */
    I2C_Open(I2C, 100000);
   
     /* Set I2C 4 Slave Addresses */            
    I2C_SetSlaveAddr(I2C, 0, 0x15, 0);   /* Slave Address : 0x15 */
    I2C_SetSlaveAddr(I2C, 1, 0x35, 0);   /* Slave Address : 0x35 */
    I2C_SetSlaveAddr(I2C, 2, 0x55, 0);   /* Slave Address : 0x55 */
    I2C_SetSlaveAddr(I2C, 3, 0x75, 0);   /* Slave Address : 0x75 */

    /* Enable I2C interrupt */
    I2C_EnableInt(I2C);
    NVIC_EnableIRQ(I2C_IRQn);
}

/*---------------------------------------------------------------------------------------------------------*/
/*  Main Function                                                                                          */
/*---------------------------------------------------------------------------------------------------------*/
int32_t main (void)
{
    uint32_t i;

    /* Init System, IP clock and multi-function I/O */
    SYS_Init();     

    /* Init UART for printf */
    UART_Init();

    /*
        This sample code sets I2C bus clock to 100kHz. Then, accesses EEPROM 24LC64 with Byte Write
        and Byte Read operations, and check if the read data is equal to the programmed data.
    */
   
    printf("+-------------------------------------------------------+\n");
    printf("|    Mini51 I2C Driver Sample Code with EEPROM 24LC64    |\n");
    printf("+-------------------------------------------------------+\n");
   
    /* Init I2C to access EEPROM */
    I2C_Init();
      
                /* I2C enter no address SLV mode */
    I2C_SET_CONTROL_REG(I2C, I2C_SI | I2C_AA);
               
                for(i = 0; i < 0x100; i++)
    {
        g_u8SlvData[i] = 0;
    }
               
                /* I2C function to write data to slave */
                s_I2CHandlerFn = I2C_SlaveTRx;

                printf("\n");
    printf("I2C Slave Mode is Running.\n");

    while(1);
}



使用特权

评论回复
地板
heisexingqisi| | 2019-4-30 20:49 | 只看该作者
IIC学的不好,参考参考。

使用特权

评论回复
5
xuanhuanzi| | 2019-4-30 21:20 | 只看该作者
以前玩51都是IO模拟

使用特权

评论回复
6
598330983|  楼主 | 2019-5-2 20:40 | 只看该作者
函数指针的高级用法

使用特权

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

本版积分规则

227

主题

5279

帖子

22

粉丝