STM32F407中,USART1:RX使用DMA2_Stream5_Channel4,TX使用DMA2_Stream7_Channel4 USART2:RX使用DMA1_Stream5_Channel4,TX使用DMA1_Stream6_Channel4 USART3:RX使用DMA1_Stream1_Channel4,TX使用DMA1_Stream3_Channel4 UART4:RX使用DMA1_Stream2_Channel4,TX使用DMA1_Stream4_Channel4 UART5:RX使用DMA1_Stream0_Channel4,TX使用DMA1_Stream7_Channel4 USART6:RX使用DMA2_Stream1_Channel5,TX使用DMA2_Stream6_Channel5 SPI1:RX使用DMA2_Stream0_Channel3,TX使用DMA2_Stream3_Channel3 SPI2:RX使用DMA1_Stream3_Channel0,TX使用DMA1_Stream4_Channel0 I2C1:RX使用DMA1_Stream0_Channel7,TX使用DMA1_Stream6_Channel7,给出USART1、USART2、USART3、UART4、UART5、USART6、SPI1、SPI2、I2C1的初始化及数据收发代码,不要使用HAL库,只能使用标准库。
时间: 2023-06-25 18:07:37 浏览: 353
以下是每个外设的初始化及数据收发代码示例:
USART1:
```c
// 初始化
void USART1_Init(uint32_t baud_rate) {
RCC->APB2ENR |= RCC_APB2ENR_USART1EN; // 使能USART1时钟
// 配置GPIO
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN; // 使能GPIOB时钟
GPIOB->MODER &= ~(GPIO_MODER_MODER6 | GPIO_MODER_MODER7); // 清零PB6和PB7的模式位
GPIOB->MODER |= (GPIO_MODER_MODER6_1 | GPIO_MODER_MODER7_1); // 设置PB6和PB7为复用功能
GPIOB->AFR[0] |= (7 << 24) | (7 << 28); // 复用为USART1_TX和USART1_RX
// 配置USART1
USART1->BRR = SystemCoreClock / baud_rate; // 设置波特率
USART1->CR1 = USART_CR1_TE | USART_CR1_RE; // 使能发送和接收
USART1->CR3 = USART_CR3_DMAT | USART_CR3_DMAR; // 使能DMA发送和接收
// 配置DMA
RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN; // 使能DMA2时钟
DMA2_Stream5->CR = 0; // 清空配置
DMA2_Stream5->CR |= DMA_SxCR_CHSEL_2 | DMA_SxCR_CHSEL_0; // 选择通道4
DMA2_Stream5->CR |= DMA_SxCR_PL_0; // 设置DMA通道优先级为低
DMA2_Stream5->PAR = (uint32_t) &USART1->DR; // 设置外设地址
}
// 数据接收
uint8_t USART1_Receive() {
while (!(USART1->SR & USART_SR_RXNE)); // 等待接收完成
return USART1->DR; // 返回接收到的数据
}
// 数据发送
void USART1_Send(uint8_t data) {
while (!(USART1->SR & USART_SR_TC)); // 等待发送完成
USART1->DR = data; // 发送数据
}
```
USART2、USART3、UART4、UART5、USART6的初始化类似,只需要修改相应的寄存器地址和通道号即可。
SPI1:
```c
// 初始化
void SPI1_Init() {
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; // 使能SPI1时钟
// 配置GPIO
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; // 使能GPIOA时钟
GPIOA->MODER &= ~(GPIO_MODER_MODER5 | GPIO_MODER_MODER6 | GPIO_MODER_MODER7); // 清零PA5、PA6、PA7的模式位
GPIOA->MODER |= (GPIO_MODER_MODER5_1 | GPIO_MODER_MODER6_1 | GPIO_MODER_MODER7_1); // 设置PA5、PA6、PA7为复用功能
GPIOA->AFR[0] |= (5 << 20) | (5 << 24) | (5 << 28); // 复用为SPI1_SCK、SPI1_MISO和SPI1_MOSI
// 配置SPI1
SPI1->CR1 = SPI_CR1_SSM | SPI_CR1_SSI | SPI_CR1_MSTR; // 设置为主机模式,软件NSS
SPI1->CR2 = SPI_CR2_DS_0 | SPI_CR2_DS_1 | SPI_CR2_DS_2; // 数据长度为8位
// 配置DMA
RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN; // 使能DMA2时钟
DMA2_Stream0->CR = 0; // 清空配置
DMA2_Stream0->CR |= DMA_SxCR_CHSEL_0; // 选择通道3
DMA2_Stream0->CR |= DMA_SxCR_PL_0; // 设置DMA通道优先级为低
DMA2_Stream0->PAR = (uint32_t) &SPI1->DR; // 设置外设地址
}
// 数据发送
void SPI1_Send(uint8_t data) {
while (!(SPI1->SR & SPI_SR_TXE)); // 等待发送缓冲区为空
SPI1->DR = data; // 发送数据
}
// 数据接收
uint8_t SPI1_Receive() {
while (!(SPI1->SR & SPI_SR_RXNE)); // 等待接收完成
return SPI1->DR; // 返回接收到的数据
}
```
SPI2的初始化类似,只需要修改相应的寄存器地址和通道号即可。
I2C1:
```c
// 初始化
void I2C1_Init(uint32_t clock_speed) {
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; // 使能I2C1时钟
// 配置GPIO
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN; // 使能GPIOB时钟
GPIOB->MODER &= ~(GPIO_MODER_MODER6 | GPIO_MODER_MODER9); // 清零PB6和PB9的模式位
GPIOB->MODER |= (GPIO_MODER_MODER6_1 | GPIO_MODER_MODER9_1); // 设置PB6和PB9为复用功能
GPIOB->AFR[0] |= (4 << 24) | (4 << 36); // 复用为I2C1_SCL和I2C1_SDA
GPIOB->OTYPER |= GPIO_OTYPER_OT_6 | GPIO_OTYPER_OT_9; // 设置为开漏输出
GPIOB->PUPDR |= GPIO_PUPDR_PUPDR6_0 | GPIO_PUPDR_PUPDR9_0; // 设置为上拉输入
// 配置I2C1
I2C1->CR1 &= ~I2C_CR1_PE; // 禁用I2C1
I2C1->CR2 |= SystemCoreClock / 1000000; // 设置时钟频率为1MHz
I2C1->CCR |= SystemCoreClock / (clock_speed * 2); // 设置时钟速率
I2C1->TRISE = SystemCoreClock / 1000000 + 1; // 设置最大上升时间
I2C1->CR1 |= I2C_CR1_PE; // 使能I2C1
}
// 发送数据
int I2C1_Send(uint8_t address, uint8_t *data, uint16_t length) {
// 等待空闲状态
while (I2C1->SR2 & I2C_SR2_BUSY);
// 发送START信号
I2C1->CR1 |= I2C_CR1_START;
while (!(I2C1->SR1 & I2C_SR1_SB));
// 发送地址和写模式
I2C1->DR = address << 1;
while (!(I2C1->SR1 & I2C_SR1_ADDR));
I2C1->SR2;
// 发送数据
for (uint16_t i = 0; i < length; i++) {
I2C1->DR = data[i];
while (!(I2C1->SR1 & I2C_SR1_TXE));
}
// 发送STOP信号
I2C1->CR1 |= I2C_CR1_STOP;
return 0;
}
// 接收数据
int I2C1_Receive(uint8_t address, uint8_t *data, uint16_t length) {
// 等待空闲状态
while (I2C1->SR2 & I2C_SR2_BUSY);
// 发送START信号
I2C1->CR1 |= I2C_CR1_START;
while (!(I2C1->SR1 & I2C_SR1_SB));
// 发送地址和读模式
I2C1->DR = (address << 1) | 1;
while (!(I2C1->SR1 & I2C_SR1_ADDR));
I2C1->SR2;
// 接收数据
for (uint16_t i = 0; i < length; i++) {
while (!(I2C1->SR1 & I2C_SR1_RXNE));
data[i] = I2C1->DR;
}
// 发送STOP信号
I2C1->CR1 |= I2C_CR1_STOP;
return 0;
}
```
阅读全文