|
本帖最后由 Dooo. 于 2021-5-25 18:01 编辑
对于该源码的说明:
1.作为主机和从机的配置主要为主/从机模式设置(I2C_CON)以及地址设置(I2C_TAR、I2C_SAR) 的不同。
2.例程为每500ms写8个字节或读8个字节。
3.在电机驱动中使用时建议将该程序中的延时TICKWaitms()更改为电机驱动中的计时方式。
PT32 IIC 主/从模式,参考源码如下:
#define IIC_Master_Mode 1 // define Master Mode
#define IIC_Slave_Mode 0 // define Slave Mode
#define DATANUM 8
uCHAR SlaveAddress = 0;
//
#if IIC_Master_Mode
uCHAR Master_TxRxFlag = 0; //0 主机写 1 主机读
uCHAR Master_Rxddata[DATANUM] = {0};
uCHAR Master_Rxddatacnt = 0;
uCHAR Master_RxdOKFlag = 0;
uCHAR Master_Txddata[DATANUM] = {0};
uCHAR Master_Txddatacnt = 0;
uCHAR Master_TxdOKFlag = 0;
#elif IIC_Slave_Mode
uCHAR Slave_Rxddata[DATANUM] = {0};
uCHAR Slave_Rxddatacnt = 0;
uCHAR Slave_RxdOKFlag = 0;
uCHAR Slave_Txddata[DATANUM] = {0};
uCHAR Slave_Txddatacnt = 0;
uCHAR Slave_TxdOKFlag = 0;
#endif
//-----
void I2CMConfig(uCHAR i2cx,uLONG rate)
{
uLONG fosc;
//
pI2C0Ctrl->I2C_ENABLE=0;
#if IIC_Master_Mode
pI2C0Ctrl->I2C_CON=(I2CCON_SLAVEDEN|I2CCON_RESTARTEN|I2CCON_7BITADDR_MASTER|I2CCON_SS|I2CCON_MASTEREN);//作为主机
#elif IIC_Slave_Mode
pI2C0Ctrl->I2C_CON=(I2CCON_SLAVEEN|I2CCON_RESTARTEN|I2CCON_7BITADDR_SLAVE|I2CCON_SS|I2CCON_MASTERDEN);//作为从机
#endif
//
fosc=SystemFrequency_APBClk/1000000;
switch (rate)
{
case I2CRATE_HS: //high speed
pI2C0Ctrl->I2C_CON&=~(3<<1);
pI2C0Ctrl->I2C_CON|=I2CCON_HS;
pI2C0Ctrl->I2C_HS_SCL_HCNT=(fosc*I2CHS_SCLH)/1000;
pI2C0Ctrl->I2C_HS_SCL_LCNT=(fosc*I2CHS_SCLL)/1000;
break;
case I2CRATE_FS: //fast speed
pI2C0Ctrl->I2C_CON&=~(3<<1);
pI2C0Ctrl->I2C_CON|=I2CCON_FS;
pI2C0Ctrl->I2C_FS_SCL_HCNT=(fosc*I2CFS_SCLH)/1000;
pI2C0Ctrl->I2C_FS_SCL_LCNT=(fosc*I2CFS_SCLL)/1000;
break;
case I2CRATE_SS: //standard speed
pI2C0Ctrl->I2C_CON&=~(3<<1);
pI2C0Ctrl->I2C_CON|=I2CCON_SS;
pI2C0Ctrl->I2C_SS_SCL_HCNT=(fosc*I2CSS_SCLH)/1000;
pI2C0Ctrl->I2C_SS_SCL_LCNT=(fosc*I2CSS_SCLL)/1000;
break;
default: //default
break;
}
}
//-----
void I2CMInit(void)
{
//Configure GPIOB Alternate Function GPIO 端口 PB02 复用为 SCL,内部上拉,开漏输出
GPIOAfr(GPIOB,BIT02,AF2); // Set PB02 as I2C(AF2) SCL
GPIOPuPd(GPIOB,BIT02,PUD_PULLUP);
GPIOOTDR(GPIOB,BIT02,1,0);
//Configure GPIOA Alternate Function
GPIOAfr(GPIOA,BIT08,AF2); // Set PA08 as I2C(AF2) SDA
GPIOPuPd(GPIOA,BIT08, PUD_PULLUP);
GPIOOTDR(GPIOA,BIT08,1,0);
//
I2CMConfig(I2C0,I2CRATE_SS);
#if IIC_Master_Mode
I2CMIntEn(I2C0,I2CINTR_RXFULL);
pI2C0Ctrl->I2C_ISC = pI2C0Ctrl->I2C_RIS;
#elif IIC_Slave_Mode
SlaveAddress = 0x5a;
pI2C0Ctrl->I2C_ENABLE=0;
pI2C0Ctrl->I2C_SAR = SlaveAddress; //作为从机时 从机的地址设置
I2CMIntEn(I2C0,I2CINTR_TXABRT | I2CINTR_RDREQ | I2CINTR_RXFULL);
pI2C0Ctrl->I2C_ISC = pI2C0Ctrl->I2C_RIS;
I2CMDevEn(I2C0,1);
#endif
}
//-----
int main(void)
{
uCHAR cnt = 0;
#if IIC_Master_Mode
uLONG tabort = 0;
uCHAR Master_Rxdtimecnt = 0;
uCHAR Master_RxdSum = 0;
uCHAR Master_TxdSum = 0;
static uCHAR Master_RxdStatus = 0;
static uCHAR Master_TxdStatus = 0;
#elif IIC_Slave_Mode
uCHAR Slave_RxdSum = 0;
uCHAR Slave_TxdSum = 0;
#endif
//
Sys_Clk_Init();
CoreInit();
UartInit();
TICKConfig();
GPIOInit();
I2CMInit();
//
printf("Version ID=0x%lx\r\n",pSYSCtrl->SC_PID0);
printf("I2C Sample Example\r\n");
printf("SysFosc=%ldHz\r\n",SystemFrequency);
printf("SysFosc Sys=%ldHz\r\n",SystemFrequency_SysClk);
printf("SysFosc AHB=%ldHz\r\n",SystemFrequency_AHBClk);
printf("SysFosc APB=%ldHz\r\n",SystemFrequency_APBClk);
//
while(1)
{
#if IIC_Master_Mode
if(Master_TxRxFlag == 0) //Write
{
if(Master_TxdStatus == 0)
{
SlaveAddress = 0x5a;
I2CMDevAddr(I2C0,SlaveAddress); //作为主机时 从机的地址设置
I2CMDevEn(I2C0,1);
//
tabort = pI2C0Ctrl->I2C_TABORT;
Master_Txddatacnt = 0;
Master_TxdStatus = 1;
//
for(cnt= 0;cnt < DATANUM - 1; cnt++)
{
Master_Txddata[cnt] = (0xa0 + cnt);
//
Master_TxdSum += Master_Txddata[cnt];
if(cnt == DATANUM - 2)
{
Master_Txddata[DATANUM - 1] = Master_TxdSum;
Master_TxdSum = 0;
}
}
}
else if(Master_TxdStatus == 1)
{
if(Master_Txddatacnt < DATANUM)
{
if((pI2C0Ctrl->I2C_STATUS&I2CSTS_TFE) && (!(pI2C0Ctrl->I2C_STATUS&I2CSTS_ACTIVITY)))
{
I2CMByteWr(I2C0,Master_Txddata[Master_Txddatacnt]);
tabort = pI2C0Ctrl->I2C_TABORT;
if(tabort & I2CTXABRT_7BADDRNOACK)
{
printf("Write False \r\n");
TICKWaitms(500);
Master_TxdStatus = 0;
}
else
{
Master_Txddatacnt++;
if(Master_Txddatacnt == DATANUM)
{
Master_TxdOKFlag = 1;
}
}
}
}
if(Master_TxdOKFlag == 1)
{
printf("Write OK \r\n");
TICKWaitms(500);
Master_RxdStatus = 0;
Master_TxdOKFlag = 0;
Master_Txddatacnt = 0;
//
Master_TxRxFlag = 1;
Master_RxdStatus = 0;
}
}
}
else if(Master_TxRxFlag == 1) //Read
{
if(Master_RxdStatus == 0)
{
for(cnt= 0;cnt < DATANUM; cnt++)
{
Master_Rxddata[cnt] = 0;
}
//
Master_Rxddatacnt = 0;
//
SlaveAddress = 0x5a;
I2CMDevAddr(I2C0,SlaveAddress);
I2CMDevEn(I2C0,1);
pI2C0Ctrl->I2C_DATA_CMD = I2CRD;
//
Master_RxdStatus = 1;
}
else if(Master_RxdStatus == 1)
{
if(Master_RxdOKFlag == 1)
{
Master_Rxdtimecnt = 0;
for(cnt= 0;cnt < DATANUM - 1; cnt++)
{
Master_RxdSum += Master_Rxddata[cnt];
if(cnt == DATANUM - 2)
{
if(Master_RxdSum == Master_Rxddata[DATANUM - 1])
{
printf("Read OK \r\n");
}
else
{
printf("Read False \r\n");
}
//
Master_RxdSum = 0;
}
}
TICKWaitms(500);
Master_RxdStatus = 0;
Master_RxdOKFlag = 0;
Master_Rxddatacnt = 0;
//
Master_TxRxFlag = 0;
Master_TxdStatus = 0;
}
else
{
TICKWaitms(1); //可替换为其他计时方式
Master_Rxdtimecnt++;
if(Master_Rxdtimecnt > 10) //一段时间内数据没收完直接报错
{
Master_Rxdtimecnt = 0;
printf("Read False \r\n");
TICKWaitms(500);
Master_RxdStatus = 0;
}
}
}
}
#elif IIC_Slave_Mode
if(Slave_RxdOKFlag == 1)
{
for(cnt= 0;cnt < DATANUM - 1; cnt++)
{
Slave_RxdSum += Slave_Rxddata[cnt];
if(cnt == DATANUM - 2)
{
if(Slave_RxdSum == Slave_Rxddata[DATANUM - 1])
{
printf("Slave Read OK \r\n");
}
else
{
printf("Slave Read False \r\n");
}
//
Slave_RxdSum = 0;
}
}
for(cnt= 0;cnt < DATANUM - 1; cnt++)
{
Slave_Txddata[cnt] = Slave_Rxddata[cnt] + 0x10;
//
Slave_TxdSum += Slave_Txddata[cnt];
if(cnt == DATANUM - 2)
{
Slave_Txddata[DATANUM - 1] = Slave_TxdSum;
Slave_TxdSum = 0;
}
}
//
Slave_RxdOKFlag = 0;
Slave_Rxddatacnt = 0;
//
Slave_Txddatacnt = 0;
}
if(Slave_TxdOKFlag == 1)
{
printf("Slave Write OK \r\n");
Slave_TxdOKFlag = 0;
Slave_Txddatacnt = 0;
//
Slave_Rxddatacnt = 0;
}
#endif
}
}
//-----
void I2C_IRQHandler(void)
{
uCHAR TempData = 0;
uLONG ris = pI2C0Ctrl->I2C_RIS;
//
#if IIC_Master_Mode
if(ris & I2CINTR_RXFULL)
{
TempData = pI2C0Ctrl->I2C_DATA_CMD;
if(Master_Rxddatacnt < DATANUM)
{
Master_Rxddata[Master_Rxddatacnt] = TempData;
Master_Rxddatacnt++;
if(Master_Rxddatacnt == DATANUM)
{
Master_RxdOKFlag = 1;
}
else
{
Master_RxdOKFlag = 0;
pI2C0Ctrl->I2C_DATA_CMD = I2CRD;
}
}
else
{
Master_Rxddatacnt = DATANUM;
}
}
#elif IIC_Slave_Mode
if(ris & I2CINTR_RDREQ)
{
pI2C0Ctrl->I2C_DATA_CMD = Slave_Txddata[Slave_Txddatacnt];
Slave_Txddatacnt++;
if(Slave_Txddatacnt >= DATANUM)
{
Slave_Txddatacnt = 0;
Slave_TxdOKFlag = 1;
}
}
else if(ris & I2CINTR_TXABRT)
{
Slave_Txddatacnt = 0;
}
//
if(ris & I2CINTR_RXFULL)
{
TempData = pI2C0Ctrl->I2C_DATA_CMD;
if(Slave_Rxddatacnt < DATANUM)
{
Slave_Rxddata[Slave_Rxddatacnt] = TempData;
Slave_Rxddatacnt++;
if(Slave_Rxddatacnt == DATANUM)
{
Slave_RxdOKFlag = 1;
}
else
{
Slave_RxdOKFlag = 0;
}
}
else
{
Slave_Rxddatacnt = DATANUM;
}
}
#endif
//
pI2C0Ctrl->I2C_ISC = ris;
}
|
|