这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » 国产MCU » 学习AI8051开发板例程:32AI8051的IIC以DMA方式进行主机通讯

共2条 1/1 1 跳转至

学习AI8051开发板例程:32AI8051的IIC以DMA方式进行主机通讯

高工
2026-03-07 13:30:39     打赏

    AI8051内置了硬件的IIC,在之前的帖子中分享了IIC读取AT24C02的数据,这里分享一下硬件IIC使用DMA的方式进行数据的存储与读取。

    基本的实现思路是:配置硬件IIC从机/主机模式,设置DMA通道,将内存中的数据通过DMA自动传输到IIC外设,从而发送到IIC存储设备。

 一:几个关键的寄存器

   首先,需要明确几个关键寄存器的分工,这对于正确配置至关重要。

    DMA_I2CT_AMT / DMA_I2CR_AMT:这是控制寄存器,用于设置DMA发送或接收通道需要传输的总字节数,每次传输的数据需要提前配置好。

    DMA_I2C_ST:这是一个状态寄存器,用于监控DMA传输的实时状态,比如传输是否完成、是否出错以及剩余字节数等。它主要用于在传输过程中或传输后进行状态查询和错误处理。

    TXAH / TXAL (发送地址寄存器):这两个寄存器用于指定DMA传输的源数据起始地址(即你要发送的数据在哪儿)。如果你的数据存储在xdata区域的数组array中,你需要将数组的24位地址分解,低8位赋值给TXAL,高8位赋值给TXAH。

二 配置过程中需要注意的地方:

    DMA只负责数据传输阶段:这是一个非常重要的概念。DMA启动后,确实会自动处理IIC总线上的数据bit流时序,但起始条件(START)、停止条件(STOP)以及从机地址的发送,通常仍需通过操作IIC控制寄存器由CPU来触发。

    流程一般是:CPU发起起始信号和从机地址 -> 确认从机应答后 -> 启动DMA传输数据 -> 数据传完后,CPU再发起停止信号。

    数据存储位置:用于DMA传输的数据缓冲区必须定义在 xdata 区域。因为DMA控制器直接访问的是扩展内存(xdata),无法访问有限的内部直接寻址内存(data/idata)。

    无阻塞式数据传输:利用DMA的一大优势就是可以实现“无阻塞”传输。CPU配置好DMA并启动后,就可以立即去处理其他任务,数据传输完全由硬件在后台完成,极大地提高了CPU的利用率。

三:软件代码:

3.1 IIC的初始化:

void DMA_Config(void)
{
    DMA_I2CT_STA = 0x00;
    DMA_I2CT_CFG = 0x80;	//bit7 1:Enable Interrupt
    DMA_I2CT_AMT = 0xff;	//设置传输总字节数(低8位):n+1
    DMA_I2CT_AMTH = 0x00;	//设置传输总字节数(高8位):n+1
    DMA_I2CT_TXAH = (u8)((u16)&DmaTxBuffer >> 8);	//I2C发送数据存储地址
    DMA_I2CT_TXAL = (u8)((u16)&DmaTxBuffer);
    DMA_I2CT_CR = 0x80;		//bit7 1:使能 I2CT_DMA, bit6 1:开始 I2CT_DMA

    DMA_I2CR_STA = 0x00;
    DMA_I2CR_CFG = 0x80;	//bit7 1:Enable Interrupt
    DMA_I2CR_AMT = 0xff;	//设置传输总字节数(低8位):n+1
    DMA_I2CR_AMTH = 0x00;	//设置传输总字节数(高8位):n+1
    DMA_I2CR_RXAH = (u8)((u16)&DmaRxBuffer >> 8);	//I2C接收数据存储地址
    DMA_I2CR_RXAL = (u8)((u16)&DmaRxBuffer);
    DMA_I2CR_CR = 0x81;		//bit7 1:使能 I2CT_DMA, bit5 1:开始 I2CT_DMA, bit0 1:清除 FIFO

    DMA_I2C_ST1 = 0xff;		//设置需要传输字节数(低8位):n+1
    DMA_I2C_ST2 = 0x00;		//设置需要传输字节数(高8位):n+1
}

3.2 使用IIC 写入多个字节

void WriteNbyte(u8 addr, u8 number)  /*  WordAddress,First Data Address,Byte lenth   */
{
    while(I2CMSST & 0x80);  //检查I2C控制器忙碌状态

    DmaTxFlag = 1;
    DmaTxBuffer[0] = SLAW;
    DmaTxBuffer[1] = addr;

    I2CMSST = 0x00;
    I2CMSCR = 0x89;             //set cmd //write_start_combo
    DMA_I2C_CR = 0x01;
    DMA_I2CT_AMT = number+1;    //设置传输总字节数(低8位):number + 设备地址 + 存储地址
    DMA_I2CT_AMTH = 0x00;       //设置传输总字节数(高8位):n+1
    DMA_I2C_ST1 = number+1;     //设置需要传输字节数(低8位):number + 设备地址 + 存储地址
    DMA_I2C_ST2 = 0x00;         //设置需要传输字节数(高8位):n+1
    DMA_I2CT_CR |= 0x40;        //bit7 1:使能 I2CT_DMA, bit6 1:开始 I2CT_DMA

    while(DmaTxFlag);           //DMA忙检测
    DMA_I2C_CR = 0x00;
}

3.3 使用IIC 读取多个字节

void ReadNbyte(u8 addr, u8 number)   /*  WordAddress,First Data Address,Byte lenth   */
{
    while(I2CMSST & 0x80);    //检查I2C控制器忙碌状态
    DMA_I2C_CR = 0x00;
    I2CMSST = 0x00;

    //发送起始信号+设备地址+写信号
    I2CTXD = SLAW;
    I2CMSCR = 0x09;
    while ((I2CMSST & 0x40) == 0);
    I2CMSST = 0x00;

    //发送存储器地址
    I2CTXD = addr;
    I2CMSCR = 0x0a;
    while ((I2CMSST & 0x40) == 0);
    I2CMSST = 0x00;
    
    //发送起始信号+设备地址+读信号
    I2CTXD = SLAR;
    I2CMSCR = 0x09;
    while ((I2CMSST & 0x40) == 0);
    I2CMSST = 0x00;

    DmaRxFlag = 1;
    //触发数据读取命令
    I2CMSCR = 0x8b;
    DMA_I2C_CR = 0x01;

    DMA_I2CR_AMT = number-1;    //设置传输总字节数(低8位):n+1
    DMA_I2CR_AMTH = 0x00;       //设置传输总字节数(高8位):n+1
    DMA_I2C_ST1 = number-1;     //设置需要传输字节数(低8位):number + 设备地址 + 存储地址
    DMA_I2C_ST2 = 0x00;         //设置需要传输字节数(高8位):n+1
    DMA_I2CR_CR |= 0x40;        //bit7 1:使能 I2CT_DMA, bit5 1:开始 I2CT_DMA, bit0 1:清除 FIFO
    while(DmaRxFlag);           //DMA忙检测
    DMA_I2C_CR = 0x00;
}

3.4  IIC的DMA中断服务函数

void I2C_DMA_Interrupt(void) interrupt 13
{
    if(DMA_I2CT_STA & 0x01)     //发送完成
    {
        DMA_I2CT_STA &= ~0x01;  //清除标志位
        DmaTxFlag = 0;
    }
    if(DMA_I2CT_STA & 0x04)     //数据覆盖
    {
        DMA_I2CT_STA &= ~0x04;  //清除标志位
    }

    if(DMA_I2CR_STA & 0x01)     //接收完成
    {
        DMA_I2CR_STA &= ~0x01;  //清除标志位
        DmaRxFlag = 0;
    }
    if(DMA_I2CR_STA & 0x02)     //数据丢弃
    {
        DMA_I2CR_STA &= ~0x02;  //清除标志位
    }
}





关键词: AI8051     DMA     IIC    

院士
2026-03-07 16:31:54     打赏
2楼

谢谢分享,学习了。


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]