This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] LAUNCHXL-F28027F:具有 FIFO 中断的 F28027F I2C

Guru**** 2608865 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/682830/launchxl-f28027f-f28027f-i2c-with-fifo-interrupt

器件型号:LAUNCHXL-F28027F

你(们)好

我正在修改显示在 OLED SSD1308上的69M 代码、信息

遗憾的是、在运行速度慢得多且没有 FPU 的27F 上、我的 ADC ISR 需要大量时间、因此恰好会切断在 I2C 上发送屏幕的主循环的传输。

在硬件 问题中运行后  、我现在正在修改代码并将其更改为使用 TX FIFO 中断

代码必须发送、命令(2个字节或3个字节和数据9个字节)、因此 FIFO 不能立即使用、我需要在 FIFO TX 上生成一个中断、以查看发送9个字节4 x 4……

我设法使用 TX FIFO 中断(它被触发)、但它不会对9个字节进行切片并仅发送4个字节...

enable_protected_register_write_mode;
PieCtrlRegs.PIEIER8.bit.INTx2 = 1;//在 PIE 中启用 I2C 中断2:组8中断2
IER |= M_INT8;//启用连接到 PIE 组8
的 CPU INT8 disable_protected_register_write_mode;
///----------------------------------
// InitI2C -此函数将 I2C 初始化为已知状态。
void InitI2C()
{
//初始化 I2C-A
I2cRegs.I2CMDR.ALL = 0x0000;
I2cRegs.I2SAR = I2C_SLAVE_ADDR;//从地址
// 90 MHz/(((8+1)(10+5 + 5+5))= 400 kHz
// 60 MHz/((5+1)(10+5 + I2CSC+5)


= 2 I2CCPLESC+5 = 4 /全部2 I2LCPL5 / I2LCPL5 = 4。//预分频器-在模块 clk
I2cRegs.I2CCLKL = 10上需要7-12MHz;//注:必须是非零
I2cRegs.I2CCLKH = 5;//注:必须是非零

// I2cirRegs.I2CIER = 0x24;// SCD & I2AR.0100

;中断= 0X0X0XI2AR.I2CIER = 0100;/中断= 0X0XI2AR.I2AR.I2AR.I0100//寻址为从机中断使能位
// I2cirRegs.I2CIER.bit.SCD = 1;//停止条件检测到的中断使能位
// I2cirRegs.I2CIER.bit.XRDY = 0;//发送数据就绪中断使能位
// I2cir.bit.I2r.I2I
=
0;//接收数据就绪中断就绪= 0;I2CIEr.I2I2I2ARRn = 0//无确认中断使能位
// I2caRegs.I2CIER.bit.ARBL = 0;//仲裁丢失中断使能位

// I2caRegs.I2CFFTX.ALL = 0x6000;//启用 FIFO 模式和 TXFIFO
I2caRegs.I2CFFTX.BIS= 1
;//启用 TX2CFI2RF1.I1/ TXIF.I2RFIF.I2RFIF.I1/ TXIF.I2RFIF.I2RFIF.I2RF1.T1.T1.I2RFIF.I2RFIF.I1/位发送 FIFO
//清除 TXFFINT 标志
I2CARegs.I2CFFTX.bit.TXFFIENA=1;// TXFFINT 标志在置
位 I2CARegs.I2CFFTX.bit.TXFFIL = 0时生成中断;//发送 FIFO 中断级别

//I2CARFX.ALL = 0xCFFI2RFIF.BIT.0**
无 RXFFI2RFIFT.I2RFIFT.TX.I2RFIF0**位;//发送 FIFO 中断 RFIFT.I2RFIF0**
//清除 RXFFINT 标志
I2CARegs.I2CFFRX.bit.RXFFIENA=0;//当置位
I2CARegs.I2CFFRX.bit.RXFFIL = 0时、RXFFINT 标志会生成一个中断;//接收 FIFO 中断级别

//I2CARegs.I2CMDR.ALL = 0xI2CMDR.0时、RXFFIL = 0;//接收 FIFO 中断位/I2CA.I2CMDR.I2CMDR.0;当暂停
时、I2I2I2CMDR.I2I2CMDR.0 = 0 =
0;/停止 I2I2I2I2I2I2CMDR.I2I2I2CMDR.I2I2CMDR//暂停
I2caRegs.I2CMDR.bit.STT = 0时停止 I2C;//开始条件位
I2caRegs.I2CMDR.bit.STP = 0;//停止条件位
I2caRegs.I2CMDR.bit.MST = 0;//从模式
I2caRegs.I2CMDR.0 =

0;/ I2c.I2c.I2e.I2c.0;/ I2ca-R2.I2e.I2e.I2c.R2.ICMT.0 = 0;/位重复模式
//数字回送模式被禁用
I2caRegs.I2CMDR.bit.IRS = 1;// I2C 模块被启用
I2caRegs.I2CMDR.bit.STB = 0;// I2C 模块不在起始字节模式
I2caRegs.I2CMDR.bit.FDF = 0;//自由数据格式
I2cA.BC.0被禁用//每个数据字节8位
I2caRegs.I2CFFTX.bit.TXFFINTCLR = 1;//清除 TXFFINT 标志

oledInit ();
//oledClear ();
}
//-----
// i2c_int2a_isr - I2C-ATX FIFO 为 int2a
中断空 i2c_int2a_isr (void)
{
uint8 fin、i;
uint16 IntSource = I2cRegs.I2CISRC.all;//读取中断源
/GPIO_setHigh (halRunle->gpioHandle、GPIO_Number= I2C_RUNIT/GPIOLED.


)
;//读取中断源/GPIORUN/GPIOUNIT.S34 = GPIOLED/中断源/GPIOUN/GPIOLED/中断源代码= GPIORUN/GPIOUN/GPIOLED/中断状态= GPIOUN/GPIOUN/GPIOUN/GPIOUNIT

//中断源=寄存器访问就绪
//此中断用于确定 EEPROM 地址设置//
读取数据通信的一部分何时完成。 由于
没有命令的停止位//、这个标志告诉我们何时发送消息而不是
// SCD 标志。 如果接收到 NACK、清除 NACK 位并命令 A
//停止。 否则、请转到通信的读取数据部分。

如果(Regerpos >= bufferend)I2cRegs.I2CMDR.bit.STP= 1;//手动设置停止

//if (((IntSource = I2C_TX_ISRC)&&(bufferpos < bufferend)
) if ((I2casRegs.I2CFFTX.bit.TXFFRC);

&I = 1

)(对于 bufferfin = 1);(对于 bufferfin = 1)/fin =
1);(对于 bufferfin = 1、I = 1);对于 bufferfin 2 (对于 bufferfin = 1、I = 1) =bufferend)I2cRegs.I2CMDR.bit.STP = 1;//手动设置停止
}

//启用未来的 I2C (PIE 组8)中断
PieCtrlRegs.PIEACK.all = PIEACK_group8;
//GPIO_setLow (halHandle->gpioDataHandle、GPIO_Number_GPIO34)
---1----


void i2c_Xfer (
uint8 address、
uint8* wdata、int wsize、
uint8* RDATA、int rsize)
{
uint16 i;
//I2cRegs.I2CMDR.bit.IRS = 0;
//usDelay (10);
//I2cRegs.I2CMDR.bit.I2b


= 1;//确保 I2CSTR/忙/中断//忙环路
//I2cRegs.I2CSTR.bit.SCD = 1;//清除 SCD 位(停止条件位)
//while (I2cRegs.I2CMDR.bit.STP = 1);//停止位环路

I2cRegs.I2CSAR =地址;// I2C 从器件地址
//while (I2cRegs.I2CSTR.bit.BB = 1);//仍然忙?

I2caRegs.I2CCNT = wsize;//设置要发送的字节数

//I2caRegs.I2CMDR.ALL = 0x6E20;//发送 TX FIFO:0110 1110 0010 0000
//I2caRegs.I2CMDR.ALL = 0x6620;// STT=1:0110 0110
I2CR.0000
= 0110 I2110.TCLR = 0110.I2CART.0110//清除 TXFFINT 标志

//I2cRegs.I2CMDR.BICKMOD = 0;// NACK 模式位
//I2cRegs.I2CMDR.BIT.FREE = 1;//在挂起时运行免费 I2C
//I2cRegs.bit.STT = 1;// I2CMT.I2CMT.BIS.R=

1;//停止条件// I2CMT.BICMP= 1
;/位/ I2CMP= 1//发送器模式
//I2cRegs.I2CMDR.bit.xa = 0;// 7位寻址模式
//I2cRegs.I2CMDR.bit.RM = 0;//非重复模式
//I2cRegs.I2CMDR.bit.DLB = 0;//数字回路模式被禁用
// I2cA.I2CMDR.I2I= 0
;I2I2I2CMDR.I2I = 0;I2AR.I2ARM.I2I2ARM.I2ARM.I2I2ARM.I2ARM.I2ART.I2ARM.A = 0// I2C 模块不在起始字节模式
//I2cRegs.I2CMDR.bit.FDF = 0;//禁用自由数据格式模式
//I2cRegs.I2CMDR.bit.BC = 0;//每个数据字节8位
//int WaitOut Timet=0;

bufferpos = 0;


I size = 0;I size = 4;for transfer end 4) fin=4;

I2caRegs.I2CFFTX.bit.TXFFINTCLR = 1;//清除
(i=0;i = bufferend)I2cRegs.I2CMDR.bit.STP= 1;//手动停止集

}
/../../---------------
void i2c_wait (int cycles)
{
I2C_WaitCount = 0;
while (I2C_WaitCount < cycles);
}
//---------------
void i2c_Reset()
{}//------------------


// SSD1308 OLED 例程
//

#define SSD1308_Address I2C_SLAVE_ADDR
#define SSD1308_Command_Mode0x80
#define SSD1308_Data_Mode 0x40
#define SSD1308_Display_OFF_Cmd 0xAE
#define SSD1308_Display_ON_Cmd 0xAF
#define SSD1308_Normal_Display_Cmd 0xA6
#define SSD1308_Invise_Display_Cmd0xA7
#define SSD1308_Active_Scroll _Cmd0x2F
#define SSD1308_DecTIVATE_Scroll _Cmd 0x2E
#define SSD1308_Set_Brightness_Cmd 0x81

const UINT8 OledFont[][8]=
{..
(笑声)
};

void oledCommand( uint8 ch ){

uint8字节[2];
字节[0]= SSD1308_Command_Mode;
字节[1]=通道;
I2C_Xfer (SSD1308_Address、bytes、2、NULL、0);
I2C_WAIT (2);
}


void oledDisplayOffset (uint8 offset)
{
uint8字节[3];
字节[0]= SSD1308_Command_Mode;
字节[1]= 0xD3;
字节[2]=偏移量;
I2C_Xfer (SSD1308_Address、bytes、3、NULL、0);
I2C_WAIT (3);
}


void oledData( uint8 data )
{
uint8字节[2];
字节[0]= SSD1308_Data_Mode;
字节[1]=数据;
I2C_Xfer (SSD1308_Address、bytes、2、NULL、0);
I2C_WAIT (3);
}


void oledGotoYX (unsigned char 行、unsigned char 列)
{
oledCommand (0xB0 + Row);
oledCommand( 0x00+(8*Column & 0x0F));
oledCommand( 0x10 +((8*Column>>4)&0x0F)));
}


void oledPutChar( char ch ){

if ((ch < 32)||(ch > 127))
CH =';

const uint8 * base =&OledFont[ch - 32][0];

uint8字节[9];
字节[0]= SSD1308_Data_Mode;
memmove (bytes + 1、base、8);
I2C_Xfer (SSD1308_Address、Bytes、9、NULL、0);
I2C_WAIT (9);
}

。
(笑声)
//我使用

oledPutChar ('a')调用例程;

似乎它在开始时进入2倍于 ISR TX FIFO、在这里、我只期望在发送的前4个字节时进入 FIFO、所以我可以添加4个字节、然后是剩余的1个字节

(如果 出现错误、i2c_wait 函数将等待命令或数据发送、转到下一个字节块

I2C_WaitCount 由 ADC ISR 更新、但实际上不需要、_仅从先前使用的中断 XRDY 函数/中断 XRDY 函数尝试更新)

关于如何解决该问题或其他解决方案的任何想法或建议?

谢谢

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Lotfi、

    在代码中、您还可以在几个位置设置停止条件。 您是否确定其中一项设置不是太早? (注意:请澄清在您的采集中、SCL 数据末尾的"P"是否表示停止、对吧?)

    此外、您还可以考虑使用非重复模式、但要设置 I2CCNT 寄存器来告知 I2C 要发送多少字节。 只是一个想法。 这样、在所需的数据量传输完毕后、I2C 就可以自行处理停止位设置。

    -Mark
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Mark

    是 P 在逻辑分析器件上停止、A 是 Acknelge、S 是 Start、W:3Ch 是到驱动器0x3C 器件的写入顺序

    if (bufferpos >= bufferend) I2caRegs.I2CMDR.bit.STP= 1; 

    当 FIFO TX ISR 发送9个字节(示例中的)时、用于终止顺序

    在执行该操作之前、我使用非重复模式(Rm=0)、但 I2C 模块无法输出停止位、并且我发现 I2C 流以旧封装的2个字节开头、然后输出底座、后跟一些字节、这是错误的。

    因此、我选择了 Rm=1、输出我自己的 Stop。

    我的实际问题是我没有看到9个字节

    我需要的是、将前4个字节发送到 FIFO (不带 TX FIFO ISR)、然后、当 FIFO 为空时、调用 ISR、再发送4个字节、然后 ISR 将再次输入以发送剩余的1个字节。

    RunLed_34指示我们何时进入 TX FIFO ISR

    InfoLED_12指示进程的开始。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我通过以下方法解决了我的问题:完全不使用 ISR、使用旧方法、但使用 Rm=1和 FIFO、我自己控制停止位、发送字节、在每个 TX 处等待 XRDY

    然后发送停止位并等待它出现(非常重要)、然后返回在 I2C 上发送下一个数据

    这是代码、但我还将发布 GitHub 上 OLED 的完整更新代码

    ///----------------------------------
    // InitI2C -此函数将 I2C 初始化为已知状态。
    void InitI2C()
    {
    //初始化 I2C-A
    //*
    I2caRegs.I2CSAR = I2C_SLAVE_ADDR;//从地址- OLED 控制代码
    //(I2C_SLAVE_ADDR << 1)|(HASWrite? 0x00:0x01);
    I2caRegs.I2CPSC.all = 6;//预分频器-模块时需要7-12MHz
    I2caRegs.I2CCLKL = 10;//注意:必须为非零
    I2caRegs.I2CCLKH = 5;//注意:必须为非零
    I2caRegs.I2CIER.ALL = 0x24;//启用 SCD 和 ARDY 中断
    //使 I2C 退出复位。 暂停时停止 I2C
    I2caRegs.I2CMDR.ALL = 0x0020;
    
    I2caRegs.I2CFFTX.ALL = 0x6000;//启用 FIFO 模式和 TXFIFO
    I2cRegs.I2CFFRX.ALL = 0x2040;//启用 RXFIFO、清除 RXFFINT、
    
    i2c1Reset ();
    //i2c1Enable (kI2C_400KHZ);
    */
    I2cRegs.I2CMDR.ALL = 0x0000;
    I2cA Regs.I2CMSAR =
    
    5MHZ (5+5MHZ)/ I2CCP+5MHZ (5+5MHZ)/ I2MCLK = 5MFF/I2DCMDR+5);
    
    / I2MCLK (5M+I2M/CC+5)(5+I2MCLK = 5+I2MHZ)/ I2MCLK = 5M/CC+I2M12+I2MCLK (5M/CCP+I2MHZ)/ I2MCLK = 5+I2M/CLCP+5)
    //预分频器-在模块 clk
    I2cRegs.I2CCLKL = 10上需要7-12MHz;//注:必须是非零
    I2cRegs.I2CCLKH = 5;//注:必须是非零
    
    // I2cirRegs.I2CIER = 0x24;// SCD & I2AR.0100
    
    ;中断= 0X0X0XI2AR.I2CIER = 0100;/中断= 0X0XI2AR.I2AR.I2AR.I0100//寻址为从机中断使能位
    // I2cirRegs.I2CIER.bit.SCD = 1;//停止条件检测到的中断使能位
    // I2cirRegs.I2CIER.bit.XRDY = 0;//发送数据就绪中断使能位
    // I2cir.bit.I2r.I2I
    =
    0;//接收数据就绪中断就绪= 0;I2CIEr.I2I2I2ARRn = 0//无确认中断使能位
    // I2caRegs.I2CIER.bit.ARBL = 0;//仲裁丢失中断使能位
    
    // I2caRegs.I2CFFTX.ALL = 0x6000;//启用 FIFO 模式和 TXFIFO
    I2caRegs.I2CFFTX.BIS= 1
    ;//启用 TX2CFI2RF1.I1/ TXIF.I2RFIF.I2RFIF.I1/ TXIF.I2RFIF.I2RFIF.I2RF1.T1.T1.I2RFIF.I2RFIF.I1/位发送 FIFO
    //清除 TXFFINT 标志
    I2CARegs.I2CFFTX.bit.TXFFIENA=0;// TXFFINT 标志在置
    位 I2CARegs.I2CFFTX.bit.TXFFIL = 0时生成中断;//发送 FIFO 中断级别
    
    //I2CARFX.ALL = 0xCFFI2RFIF.BIT.0**
    无 RXFFI2RFIFT.I2RFIFT.TX.I2RFIF0**位;//发送 FIFO 中断 RFIFT.I2RFIFT.I2RFIF0**
    //清除 RXFFINT 标志
    I2CARegs.I2CFFRX.bit.RXFFIENA=0;//当置位
    I2CARegs.I2CFFRX.bit.RXFFIL = 0时、RXFFINT 标志会生成一个中断;//接收 FIFO 中断级别
    
    //I2CARegs.I2CMDR.ALL = 0xI2CMDR.0时、RXFFIL = 0;//接收 FIFO 中断位/I2CA.I2CMDR.I2CMDR.0;当暂停
    时、I2I2I2CMDR.I2I2CMDR.0 = 0 =
    0;/停止 I2I2I2I2I2I2CMDR.I2I2I2CMDR.I2I2CMDR//暂停
    I2caRegs.I2CMDR.bit.STT = 0时停止 I2C;//开始条件位
    I2caRegs.I2CMDR.bit.STP = 0;//停止条件位
    I2caRegs.I2CMDR.bit.MST = 0;//从模式
    I2caRegs.I2CMDR.0 =
    
    0;/ I2c.I2c.I2e.I2c.0;/ I2ca-R2.I2e.I2e.I2c.R2.ICMT.0 = 0;/位重复模式
    //数字回送模式被禁用
    I2caRegs.I2CMDR.bit.IRS = 1;// I2C 模块被启用
    I2caRegs.I2CMDR.bit.STB = 0;// I2C 模块不在起始字节模式
    I2caRegs.I2CMDR.bit.FDF = 0;//自由数据格式
    
    
    (I2caR = 0)
    ;Ioledbytes = 0;I2byte.I2ced.I2bc = 0
    oledGotoYX( 0, 0);
    oledPrint(“环”);
    oledGotoYX( 1,0);
    oledPrint("Thompson");
    oledGotoYX( 2,0);
    oledPrint("Vs:");
    oledGotoYX(2,14);
    oledPrint("V");
    oledGotoYX(3, 0);
    oledPrint ("FS:");
    oledGotoYX (3、14);
    oledPrint ("Hz");
    }
    ///----------------------------------
    void i2c_Xfer (
    uint8 address、
    uint8* wdata、int wsize、
    uint8* RDATA、int rsize)
    {
    uint16 i;
    //I2cRegs.I2CMDR.bit.IRS = 0;
    //usDelay (10);
    //I2cRegs.I2CMDR.bit.I2b
    
    
    = 1;//确保 I2CSTR/忙/中断//忙环路
    //I2cRegs.I2CSTR.bit.SCD = 1;//清除 SCD 位(停止条件位)
    //while (I2cRegs.I2CMDR.bit.STP = 1);//停止位环路
    
    I2cRegs.I2CSAR =地址;// I2C 从器件地址
    //while (I2cRegs.I2CSTR.bit.BB = 1);//仍然忙?
    
    I2caRegs.I2CCNT = wsize;//设置要发送的字节数
    
    //I2caRegs.I2CMDR.ALL = 0x6E20;//发送 TX FIFO:0110 1110 0010 0000
    //I2caRegs.I2CMDR.ALL = 0x6620;// STT=1:0110 0010 0000
    ;I2caR=0110 0660000;I2caR=0110 = 012100.I2e.01000160A0160I2E/ I2aR 0110 0110 1010 0000RM、STT
    
    //I2cRegs.I2CMDR.BICKMOD= 0;// NACK 模式位
    //I2cRegs.I2CMDR.BICAR.FREE = 1;//暂停时运行免费 I2C
    //I2cRegs.I2CMDR.STT= 1;//停止条件
    / I2CMT.STP/位= 1;/ I2CMT.BICMP/位条件
    //主控模式
    //I2cRegs.I2CMDR.bit.TRX = 1;//发送器模式
    //I2cRegs.I2CMDR.bit.XA = 0;// 7位寻址模式
    //I2cRegs.I2CMDR.bit.RM = 0;//非重复模式
    //I2CC.I2CMDR.I2I= 0;/ I2CC.I2CMDR.I2CMDR.I2I
    = 0;/ I2CMDR.I2CMDR.I2I = 0
    位/I2CMDR.I2CMDR.I2I = 0// I2C 模块不处于起始字节模式
    //I2cRegs.I2CMDR.bit.FDF = 0;//禁用自由数据格式模式
    //I2cRegs.I2CMDR.bit.BC = 0;//每个数据字节8位
    //int WaitOut Time=0;
    
    //开始传输4个字节
    (I max = 0) >4)&0x0F));
    }
    
    void oledPutChar (char ch)
    {
    如果((ch < 32)||(ch > 127) ch =';
    const uint8 * base =&OledFont[ch - 32][0];
    uint8字节[9];
    字节[0]= SSD1308_Data_Mode;
    memmove (bytes + 1、base、8);
    I2C_Xfer (SSD1308_Address、Bytes、9、NULL、0);
    }
    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    感谢博特菲发布! 我很高兴您能让它正常工作。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    GitHub 上提供的示例代码

    https://github.com/blotfi/c2000_OLED_SSD1306

    和博客