422 lines
14 KiB
C
422 lines
14 KiB
C
#include "../main/SystemInclude.h"
|
||
|
||
#ifndef ENABLE_USER_I2C
|
||
#pragma message("[undefined] ENABLE_USER_I2C")
|
||
#elif(ENABLE_USER_I2C)
|
||
|
||
DMA_HandleTypeDef DMA_Handle_IIC_Rx,DMA_Handle_IIC_Tx;
|
||
|
||
|
||
//初始化IIC
|
||
//i2c_slave_init(100000 , 0x02);
|
||
void I2C_Slave_Init(u32 clockSpeed ,u16 slaveAddress)
|
||
{
|
||
GPIO_InitTypeDef GPIO_InitStructure;
|
||
I2C_InitTypeDef I2C_InitStructure;
|
||
/* 1. 设置 I2C GPIO复用端口 */
|
||
GPIO_InitStructure.Pin = GPIO_PIN_1;
|
||
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD; // I2C SCL开漏输出
|
||
GPIO_InitStructure.Current = GPIO_CURRENT_8mA;
|
||
GPIO_InitStructure.Pull = GPIO_NOPULL;
|
||
GPIO_InitStructure.SchmittTrigger = ENABLE;
|
||
GPIO_InitStructure.Alternate = GPIO0_1_AF_SCL; // AFIO设置
|
||
LHL_GPIO_Init(GPIO0, &GPIO_InitStructure); //P0.1 P2.0 -> SCL
|
||
|
||
GPIO_InitStructure.Pin = GPIO_PIN_2;
|
||
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD; // I2C SDA开漏输出
|
||
GPIO_InitStructure.Current = GPIO_CURRENT_8mA;
|
||
GPIO_InitStructure.Pull = GPIO_NOPULL;
|
||
GPIO_InitStructure.SchmittTrigger = ENABLE;
|
||
GPIO_InitStructure.Alternate = GPIO0_2_AF_SDA; // AFIO设置
|
||
LHL_GPIO_Init(GPIO0, &GPIO_InitStructure); //P0.2 P1.4 -> SDA
|
||
|
||
/* 2. 配置 I2C 外设 */
|
||
I2C_InitStructure.ClockSpeed = clockSpeed; //100KHz Standard I2C Speed
|
||
I2C_InitStructure.DutyCycle = I2C_DutyCycle_2;
|
||
I2C_InitStructure.OwnAddress1 = slaveAddress; //Temporary slave device address
|
||
I2C_InitStructure.I2CAck = I2C_Ack_Enable;
|
||
I2C_InitStructure.AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
|
||
LHL_I2C_Init(&I2C_InitStructure);
|
||
// LHL_I2C_StretchClockCmd(DISABLE);//关闭时钟延展
|
||
LHL_I2C_ITConfig(I2C_IT_EVT|I2C_IT_BUF|I2C_IT_ERR, ENABLE);
|
||
NVIC_SetPriority(I2C1_EV_IRQn,0);
|
||
NVIC_EnableIRQ(I2C1_EV_IRQn);
|
||
}
|
||
|
||
|
||
|
||
/*********************************************************************************************************************************************/
|
||
/*中断 方式*/
|
||
/*********************************************************************************************************************************************/
|
||
I2C_DATA_TypeDef I2CData;
|
||
|
||
void I2C1_EV_IRQHandler()
|
||
{
|
||
__IO uint32_t sta1,sta2;
|
||
__IO uint32_t R_W;
|
||
|
||
sta1 = pI2C->SR1;
|
||
sta2 = pI2C->SR2; //清除STOPF
|
||
R_W = (sta2&I2C_SR2_TRA_Msk)>>I2C_SR2_TRA_Pos; //判断当前是读(Master读Slave)还是写(Master写Slave)
|
||
|
||
if(sta1 & I2C_SR1_ADDR_Msk)//I2C地址匹配
|
||
{
|
||
LHL_I2C_ClearFlag(I2C_FLAG_ADDR);
|
||
LHL_I2C_ClearFlag(I2C_FLAG_TXE);
|
||
if(R_W == MASTER_READ_SLAVE) I2CStartWriteProcess(); //更新状态参数 ,IIC从机开始发送(向主机写)寄存器地址
|
||
else I2CStartReadProcess();//更新状态参数 ,IIC开始接收数据
|
||
}
|
||
if(sta1 & I2C_SR1_STOPF_Msk)
|
||
{
|
||
LHL_I2C_ClearFlag(I2C_FLAG_STOPF);
|
||
return;
|
||
}
|
||
if(sta1 & I2C_SR1_AF_Msk) //主机发送NACK
|
||
{
|
||
I2CResetProcess(); //重置状态参数
|
||
LHL_I2C_Cmd(ENABLE);//保持IIC开启
|
||
LHL_I2C_ClearFlag(I2C_FLAG_TXE | I2C_FLAG_RXNE | I2C_FLAG_AF);
|
||
LHL_I2C_ClearFlag(I2C_FLAG_PECERR | I2C_FLAG_OVR | I2C_FLAG_BERR);
|
||
return;
|
||
}
|
||
|
||
if((sta1 & I2C_SR1_RXNE_Msk) && (R_W==MASTER_WRITE_SLAVE)) //IIC写入
|
||
{
|
||
LHL_I2C_ClearFlag(I2C_FLAG_RXNE);
|
||
I2CData.rxData[I2CData.rxCounter++] = LHL_I2C_ReceiveData();
|
||
I2CReceiveProcess();//发送处理,准备发送数据(一直收等I2C_SR1_ADDR_Msk变成主机读命令(即从机发))
|
||
return;
|
||
}
|
||
|
||
if((sta1 & I2C_SR1_TXE_Msk) && (R_W==MASTER_READ_SLAVE)) //IIC发送(单字节)
|
||
{
|
||
I2CTransmitProcess();//发送处理,当前设置为每3字节处理一次,主机没有停止接收前一直可发
|
||
LHL_I2C_SendData(I2CData.txData[I2CData.txCounter++]);
|
||
return;
|
||
}
|
||
|
||
if(sta1 & I2C_SR1_BERR_Msk) { LHL_I2C_ClearFlag(I2C_FLAG_BERR); return;} //clear BERR
|
||
__DSB();//make sure intterupt flag cleared
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
//中断 测试代码========================================================
|
||
#define TEST_BUF_LEN 20
|
||
uint8_t iic_tx_buf[TEST_BUF_LEN] = {0} ,iic_tx_len ;
|
||
uint8_t iic_rx_buf[TEST_BUF_LEN] = {0};
|
||
uint16_t iic_tx_cnt = 0;
|
||
uint16_t iic_rx_cnt = 0;
|
||
void I2C1_EV_IRQHandler2(void)//
|
||
{
|
||
__IO uint32_t sta1,sta2;
|
||
__IO uint32_t R_W;
|
||
|
||
sta1 = pI2C->SR1;
|
||
sta2 = pI2C->SR2; //清除STOPF
|
||
R_W = (sta2&I2C_SR2_TRA_Msk)>>I2C_SR2_TRA_Pos; //判断当前是读(Master读Slave)还是写(Master写Slave)
|
||
|
||
if(sta1 & I2C_SR1_ADDR_Msk)//I2C address match
|
||
{
|
||
if(R_W == MASTER_READ_SLAVE)iic_tx_cnt = 0;//主机读取数据,从机发送模式
|
||
else iic_rx_cnt = 0;//主机写入数据,从机接收模式
|
||
}
|
||
if(sta1 & I2C_SR1_STOPF_Msk)
|
||
{
|
||
pI2C->CR1 |= I2C_CR1_STOP_Msk;
|
||
}
|
||
if(sta1 & I2C_SR1_AF_Msk)
|
||
{
|
||
pI2C->CR1 |= I2C_SR1_AF_Msk; //主机nack
|
||
pI2C->SR1 &= ~I2C_SR1_AF_Msk;
|
||
|
||
|
||
|
||
|
||
}
|
||
|
||
if((sta1 & I2C_SR1_RXNE_Msk) && (R_W==0)) // write
|
||
{
|
||
//接收到写入数据
|
||
iic_rx_buf[iic_rx_cnt++] = pI2C->DR;
|
||
|
||
if(iic_rx_cnt==2)IIC_Cmd_Check_Test();
|
||
|
||
}
|
||
if((sta1 & I2C_SR1_TXE_Msk) && (R_W==1)) //trasmitted one byte
|
||
{
|
||
pI2C->DR = iic_tx_buf[iic_tx_cnt++];
|
||
}
|
||
__DSB();//make sure intterupt flag cleared
|
||
}
|
||
|
||
void IIC_Cmd_Check_Test(void)
|
||
{
|
||
u16 regcmd = (I2CData.rxData[0]<<8) + I2CData.rxData[1];
|
||
u8 i;
|
||
switch(regcmd)
|
||
{
|
||
case 0x821A:
|
||
iic_tx_buf[0] = 0x00;
|
||
iic_tx_buf[1] = 0x01;
|
||
iic_tx_buf[2] = I2CWordCrc(iic_tx_buf[0], iic_tx_buf[1]);
|
||
iic_tx_len=3;
|
||
break;
|
||
case 0x30:
|
||
iic_tx_buf[0] = 0x30;
|
||
iic_tx_buf[1] = 0x31;
|
||
iic_tx_buf[2] = I2CWordCrc(iic_tx_buf[0], iic_tx_buf[1]);
|
||
iic_tx_buf[3] = 0x40;
|
||
iic_tx_buf[4] = 0x41;
|
||
iic_tx_buf[5] = I2CWordCrc(iic_tx_buf[3], iic_tx_buf[4]);
|
||
iic_tx_buf[6] = 0x32;
|
||
iic_tx_buf[7] = 0x33;
|
||
iic_tx_buf[8] = I2CWordCrc(iic_tx_buf[6], iic_tx_buf[7]);
|
||
iic_tx_buf[9] = 0x34;
|
||
iic_tx_buf[10] = 0x35;
|
||
iic_tx_buf[11] = I2CWordCrc(iic_tx_buf[9], iic_tx_buf[10]);
|
||
iic_tx_buf[12] = 0x36;
|
||
iic_tx_buf[13] = 0x37;
|
||
iic_tx_buf[14] = I2CWordCrc(iic_tx_buf[12], iic_tx_buf[13]);
|
||
iic_tx_buf[15] = 0x38;
|
||
iic_tx_buf[16] = 0x39;
|
||
iic_tx_buf[17] = I2CWordCrc(iic_tx_buf[15], iic_tx_buf[16]);
|
||
iic_tx_len=18;
|
||
break;
|
||
case 0x36:
|
||
iic_tx_buf[0] = 0x32;
|
||
iic_tx_buf[1] = 0x33;
|
||
iic_tx_buf[2] = I2CWordCrc(iic_tx_buf[0], iic_tx_buf[1]);
|
||
iic_tx_len=3;
|
||
break;
|
||
case 0x81:
|
||
iic_tx_buf[0] = 0x01;
|
||
iic_tx_buf[1] = 0x41;
|
||
iic_tx_buf[2] = I2CWordCrc(iic_tx_buf[0], iic_tx_buf[1]);
|
||
iic_tx_len=3;
|
||
break;
|
||
case 0x3A:
|
||
iic_tx_buf[0] = 0x01;
|
||
iic_tx_buf[1] = 0x41;
|
||
iic_tx_buf[2] = I2CWordCrc(iic_tx_buf[0], iic_tx_buf[1]);
|
||
iic_tx_buf[3] = 0x40;
|
||
iic_tx_buf[4] = 0x41;
|
||
iic_tx_buf[5] = I2CWordCrc(iic_tx_buf[3], iic_tx_buf[4]);
|
||
iic_tx_len=6;
|
||
break;
|
||
|
||
case 0x3C:
|
||
iic_tx_buf[0] = 0x01;
|
||
iic_tx_buf[1] = 0x41;
|
||
iic_tx_buf[2] = I2CWordCrc(iic_tx_buf[0], iic_tx_buf[1]);
|
||
iic_tx_buf[3] = 0x40;
|
||
iic_tx_buf[4] = 0x41;
|
||
iic_tx_buf[5] = I2CWordCrc(iic_tx_buf[3], iic_tx_buf[4]);
|
||
iic_tx_buf[6] = 0x32;
|
||
iic_tx_buf[7] = 0x33;
|
||
iic_tx_buf[8] = I2CWordCrc(iic_tx_buf[6], iic_tx_buf[7]);
|
||
iic_tx_len=9;
|
||
break;
|
||
case 0x56:
|
||
iic_tx_buf[0] = 0x01;
|
||
iic_tx_buf[1] = 0x41;
|
||
iic_tx_buf[2] = I2CWordCrc(iic_tx_buf[0], iic_tx_buf[1]);
|
||
|
||
|
||
|
||
|
||
iic_tx_len=12;
|
||
break;
|
||
case 0x85:
|
||
iic_tx_buf[0] = 0x01;
|
||
iic_tx_buf[1] = 0x41;
|
||
iic_tx_buf[2] = I2CWordCrc(iic_tx_buf[0], iic_tx_buf[1]);
|
||
iic_tx_buf[3] = 0x40;
|
||
iic_tx_buf[4] = 0x41;
|
||
iic_tx_buf[5] = I2CWordCrc(iic_tx_buf[3], iic_tx_buf[4]);
|
||
iic_tx_len=6;
|
||
break;
|
||
default:
|
||
iic_tx_buf[0] = 0x30;
|
||
iic_tx_buf[1] = 0x31;
|
||
iic_tx_buf[2] = I2CWordCrc(iic_tx_buf[0], iic_tx_buf[1]);
|
||
iic_tx_len=3;
|
||
|
||
break;
|
||
}
|
||
}
|
||
|
||
|
||
void IIC_Cmd_Check_Test1(void)
|
||
{
|
||
I2CData.readAddr = (I2CData.rxData[0]<<8) + I2CData.rxData[1];
|
||
|
||
MBBuf.StartAddr = I2CData.readAddr;
|
||
MBBuf.ByteNumber = 2 ; //一次读取的数据长度
|
||
MBBuf.RxPointer = &I2CData.rxData[2]; // 读取的数据从2开始放,0,1用于存储接收到的地址
|
||
MBBuf.Index = 0;
|
||
|
||
// ModBusReadMultiByte();//根据MBBuf.StartAddr得到对应寄存器数据
|
||
// I2CData.rxData[2] = tempL.Word[0];
|
||
// I2CData.rxData[3] = tempL.Word[1];
|
||
|
||
// 获取数据个数
|
||
u8 count = 1;
|
||
switch(MBBuf.StartAddr) {
|
||
case 0x30: count = 6; break;
|
||
case 0x3A: count = 2; break;
|
||
case 0x3C: count = 3; break;
|
||
case 0x56: count = 4; break;
|
||
case 0x85: count = 2; break;
|
||
case 0xAE: count = 2; break;
|
||
default : count = 1;
|
||
}
|
||
|
||
// 生成响应
|
||
// UserReadDataProtocol();
|
||
|
||
|
||
u16 index = MBBuf.StartAddr - 0x30;//STD_REG_START
|
||
u16 data ;
|
||
u8 i , tx_idx = 0;
|
||
if(MBBuf.StartAddr > 0x30 && MBBuf.StartAddr <0x130)
|
||
{
|
||
for( i = 0; i < count; i++)
|
||
{
|
||
data = MBReg[index + i];
|
||
I2CData.txData[tx_idx++] = (data >> 8) & 0xFF;
|
||
I2CData.txData[tx_idx++] = data & 0xFF;
|
||
I2CData.txData[tx_idx++] = I2CWordCrc((data >> 8) & 0xFF, data & 0xFF);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
I2CData.txData[tx_idx++] =0x00;
|
||
I2CData.txData[tx_idx++] =0x01;
|
||
I2CData.txData[tx_idx++] = I2CWordCrc(0x00, 0x01);
|
||
}
|
||
iic_tx_len = tx_idx;
|
||
}
|
||
|
||
//中断 测试代码 end========================================================
|
||
|
||
|
||
|
||
/*********************************************************************************************************************************************/
|
||
/*DMA 方式*/
|
||
/*********************************************************************************************************************************************/
|
||
void DMA_I2C_SlaveRx_Init(void)
|
||
{
|
||
DMAMUX_InitTypeDef DMAMUX_InitStructure;
|
||
/* 配置DMAUX 请求源 RX,触发DMA通道0 */
|
||
DMAMUX_InitStructure.DMA_Channel = DMA_CHANNEL_0; // 配置DMA0触发源
|
||
DMAMUX_InitStructure.Request_Source = REQUEST_SOURCE_I2C0_RX; // 触发源I2C0_RX
|
||
DMAMUX_InitStructure.Periodic_Trigger = DISABLE; // 禁用周期触发
|
||
DMAMUX_InitStructure.Cmd = ENABLE; // 使能
|
||
LHL_DMAMUX_Init(&DMAMUX_InitStructure);
|
||
|
||
/* 配置DMA通道0,负责I2C RX数据搬运到缓存区 */
|
||
DMA_Handle_IIC_Rx.Channel = DMA_CHANNEL_0; // DMACH0
|
||
DMA_Handle_IIC_Rx.Mode = DMA_DIRECT_MODE; // 直接模式
|
||
DMA_Handle_IIC_Rx.Request = DMA_HARDWARE_REQUEST; // 硬件触发
|
||
DMA_Handle_IIC_Rx.Init.Direction = DMA_PERIPH_TO_MEMORY; // 外设->内存
|
||
DMA_Handle_IIC_Rx.Init.Src_Address = (uint32_t)(&pI2C->DR); // 源:I2C DR寄存器
|
||
DMA_Handle_IIC_Rx.Init.Dest_Address = (uint32_t)&I2CData.rxData; // 目的:缓存区
|
||
DMA_Handle_IIC_Rx.Init.Data_Width = DMA_DATA_WIDTH_1B; // 数据宽度等于寄存器宽度
|
||
DMA_Handle_IIC_Rx.Init.Data_Size = 1; // 每次读取1个寄存器
|
||
DMA_Handle_IIC_Rx.Init.Repetition = 2; // 重复读取 次
|
||
DMA_Handle_IIC_Rx.Init.Trans_Mode = DMA_CYCLIC_TRANSMISSION; // 循环模式
|
||
if (LHL_DMA_Init(&DMA_Handle_IIC_Rx) != LHL_OK)
|
||
{
|
||
while(1); // DMA Init Error
|
||
}
|
||
LHL_DMA_ITConfig(&DMA_Handle_IIC_Rx, DMA_IT_MAJOR, ENABLE); // 开启DMA0主中断
|
||
NVIC_EnableIRQ(DMA1_CH0_IRQn);
|
||
|
||
}
|
||
void DMA_I2C_SlaveTx_Init(void)
|
||
{
|
||
DMAMUX_InitTypeDef DMAMUX_InitStructure;
|
||
/* 配置DMAUX 请求源 TX,触发DMA通道1 */
|
||
DMAMUX_InitStructure.DMA_Channel = DMA_CHANNEL_1; // 配置DMA1触发源
|
||
DMAMUX_InitStructure.Request_Source = REQUEST_SOURCE_I2C0_TX; // 触发源I2C0_TX
|
||
DMAMUX_InitStructure.Periodic_Trigger = DISABLE;
|
||
DMAMUX_InitStructure.Cmd = ENABLE;
|
||
LHL_DMAMUX_Init(&DMAMUX_InitStructure);
|
||
|
||
/* 配置DMA通道1,负责缓存区数据搬运到I2C TX数据 */
|
||
DMA_Handle_IIC_Tx.Channel = DMA_CHANNEL_1; // 句柄更改为DMA1
|
||
DMA_Handle_IIC_Tx.Mode = DMA_DIRECT_MODE;
|
||
DMA_Handle_IIC_Tx.Request = DMA_HARDWARE_REQUEST;
|
||
DMA_Handle_IIC_Tx.Init.Direction = DMA_MEMORY_TO_PERIPH; // 内存->外设
|
||
DMA_Handle_IIC_Tx.Init.Src_Address = (uint32_t)&I2CData.txData; // 源:缓存区
|
||
DMA_Handle_IIC_Tx.Init.Dest_Address = (uint32_t)(&pI2C->DR); // 目的:I2C DR寄存器
|
||
DMA_Handle_IIC_Tx.Init.Data_Width = DMA_DATA_WIDTH_1B;
|
||
DMA_Handle_IIC_Tx.Init.Data_Size = 1;
|
||
DMA_Handle_IIC_Tx.Init.Repetition = iic_tx_len;
|
||
DMA_Handle_IIC_Tx.Init.Trans_Mode = DMA_SINGLE_TRANSMISSION; // 单次模式 DMA_SINGLE_TRANSMISSION DMA_INTERVAL_TRANSMISSION
|
||
if (LHL_DMA_Init(&DMA_Handle_IIC_Tx) != LHL_OK)
|
||
{
|
||
while(1); // DMA Init Error
|
||
}
|
||
LHL_DMA_ITConfig(&DMA_Handle_IIC_Tx, DMA_IT_MAJOR, ENABLE); // 开启DMA1主中断
|
||
NVIC_EnableIRQ(DMA1_CH1_IRQn);
|
||
}
|
||
|
||
void DMA_I2C_Slave_Init(u32 clockSpeed ,u16 slaveAddress)
|
||
{
|
||
I2C_Slave_Init(clockSpeed,slaveAddress);
|
||
LHL_I2C_DMACmd(ENABLE);//DMA请求使能
|
||
DMA_I2C_SlaveRx_Init();
|
||
iic_tx_len=3;
|
||
DMA_I2C_SlaveTx_Init();
|
||
LHL_DMA_Start(&DMA_Handle_IIC_Rx);
|
||
}
|
||
|
||
//for DMA
|
||
void I2C1_EV_IRQHandler3()//
|
||
{
|
||
__IO uint32_t sta1,sta2;
|
||
uint32_t R_W;
|
||
uint8_t data;
|
||
|
||
sta1 = pI2C->SR1;
|
||
sta2 = pI2C->SR2;
|
||
R_W = (sta2 & I2C_SR2_TRA_Msk)>>I2C_SR2_TRA_Pos; //write frame or read frame
|
||
if(sta1 & I2C_SR1_ADDR_Msk) //I2C address match
|
||
{
|
||
if (R_W == 1)
|
||
{
|
||
LHL_DMA_Stop(&DMA_Handle_IIC_Tx);
|
||
DMA_I2C_SlaveTx_Init();
|
||
LHL_DMA_Start(&DMA_Handle_IIC_Tx);
|
||
}
|
||
if (R_W == 0)
|
||
{
|
||
|
||
}
|
||
}
|
||
if(sta1 & I2C_SR1_STOPF_Msk)
|
||
{
|
||
pI2C->CR1 |= I2C_CR1_STOP_Msk;
|
||
}
|
||
if(sta1 & I2C_SR1_AF_Msk)
|
||
{
|
||
pI2C->CR1 |= I2C_SR1_AF_Msk; //主机nack
|
||
}
|
||
if(sta1 & I2C_SR1_AF_Msk)
|
||
{
|
||
pI2C->SR1 &= ~I2C_SR1_AF_Msk;
|
||
}
|
||
__DSB(); //make sure intterupt flag cleared
|
||
}
|
||
|
||
|
||
|
||
#endif |