写一个使用STM32F4标准库版本写的硬件IIC从机DMA代码
时间: 2024-02-13 11:02:32 浏览: 150
STM32F4 的DMA程序
以下是一个使用STM32F4标准库版本写的硬件IIC从机DMA代码,可以作为参考:
```
#include "stm32f4xx.h"
#define I2C_SLAVE_ADDRESS 0x50
#define BUFFER_SIZE 16
volatile uint8_t rxBuffer[BUFFER_SIZE];
volatile uint8_t txBuffer[BUFFER_SIZE];
volatile uint16_t txCount = 0;
volatile uint16_t rxCount = 0;
volatile uint8_t dmaInProgress = 0;
void I2C1_EV_IRQHandler(void)
{
if(I2C_GetITStatus(I2C1, I2C_IT_EVT) == SET)
{
// Check for slave address match
if(I2C_GetLastEvent(I2C1) == I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED)
{
// Clear the ADDR flag
I2C_ClearFlag(I2C1, I2C_FLAG_ADDR);
// Enable DMA reception
DMA_Cmd(DMA1_Stream0, ENABLE);
// Enable DMA1 Stream0 transfer complete interrupt
DMA_ITConfig(DMA1_Stream0, DMA_IT_TC, ENABLE);
}
else if(I2C_GetLastEvent(I2C1) == I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED)
{
// Clear the ADDR flag
I2C_ClearFlag(I2C1, I2C_FLAG_ADDR);
// Enable DMA transmission
DMA_Cmd(DMA1_Stream6, ENABLE);
// Enable DMA1 Stream6 transfer complete interrupt
DMA_ITConfig(DMA1_Stream6, DMA_IT_TC, ENABLE);
}
}
I2C_ClearITPendingBit(I2C1, I2C_IT_EVT);
}
void DMA1_Stream0_IRQHandler(void)
{
if(DMA_GetITStatus(DMA1_Stream0, DMA_IT_TCIF0) == SET)
{
// Disable DMA1 Stream0 transfer complete interrupt
DMA_ITConfig(DMA1_Stream0, DMA_IT_TC, DISABLE);
// Disable DMA reception
DMA_Cmd(DMA1_Stream0, DISABLE);
// Set the DMA in progress flag
dmaInProgress = 1;
// Enable I2C ACK
I2C_AcknowledgeConfig(I2C1, ENABLE);
}
DMA_ClearITPendingBit(DMA1_Stream0, DMA_IT_TCIF0);
}
void DMA1_Stream6_IRQHandler(void)
{
if(DMA_GetITStatus(DMA1_Stream6, DMA_IT_TCIF6) == SET)
{
// Disable DMA1 Stream6 transfer complete interrupt
DMA_ITConfig(DMA1_Stream6, DMA_IT_TC, DISABLE);
// Disable DMA transmission
DMA_Cmd(DMA1_Stream6, DISABLE);
// Set the DMA in progress flag
dmaInProgress = 1;
// Enable I2C ACK
I2C_AcknowledgeConfig(I2C1, ENABLE);
}
DMA_ClearITPendingBit(DMA1_Stream6, DMA_IT_TCIF6);
}
int main(void)
{
// Initialize I2C1
I2C_InitTypeDef I2C_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
// Enable I2C1 and DMA1 clocks
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
// Configure GPIO pins for I2C1
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// Set GPIO pins to alternate function
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1);
// Initialize I2C1
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = I2C_SLAVE_ADDRESS << 1;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = 100000;
I2C_Init(I2C1, &I2C_InitStructure);
// Enable I2C1
I2C_Cmd(I2C1, ENABLE);
// Initialize DMA1 Stream0 for reception
DMA_InitTypeDef DMA_InitStructure;
DMA_StructInit(&DMA_InitStructure);
DMA_InitStructure.DMA_Channel = DMA_Channel_1;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&I2C1->DR;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)rxBuffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = BUFFER_SIZE;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA1_Stream0, &DMA_InitStructure);
// Initialize DMA1 Stream6 for transmission
DMA_StructInit(&DMA_InitStructure);
DMA_InitStructure.DMA_Channel = DMA_Channel_1;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&I2C1->DR;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)txBuffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_BufferSize = BUFFER_SIZE;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA1_Stream6, &DMA_InitStructure);
// Enable DMA1 Stream0 and Stream6 interrupts
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream6_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// Enable I2C1 event interrupt
NVIC_InitStructure.NVIC_IRQChannel = I2C1_EV_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// Enable I2C1 address match interrupt
I2C_ITConfig(I2C1, I2C_IT_ADDRI, ENABLE);
while(1)
{
if(dmaInProgress)
{
// Data transfer complete, reset flags
dmaInProgress = 0;
txCount = 0;
rxCount = 0;
// Process received data
// ...
}
}
}
```
这个代码使用了STM32F4标准库,并且使用了DMA来进行I2C从机通信。在中断处理程序中,使用了DMA传输完成中断来检测数据传输是否完成,然后处理接收到的数据。注意,在使用DMA传输数据时,需要先启用DMA传输,然后再启用I2C ACK(应答),否则I2C从机将无法正确接收数据。
阅读全文