写一个STM32F407ZGT6的串口1在DMA模式下输出信息给OLED的代码
时间: 2024-02-27 11:55:13 浏览: 60
好的,以下是基于HAL库实现的代码示例:
```c
#include "main.h"
#include "stdio.h"
#include "string.h"
/* OLED 显示屏的 I2C 地址 */
#define OLED_ADDR 0x78
/* OLED 显示屏的宽度和高度 */
#define OLED_WIDTH 128
#define OLED_HEIGHT 64
/* OLED 显示屏的初始化命令 */
uint8_t OLED_Init_Cmd[] = {
0xAE, // 关闭显示
0xD5, 0x80, // 设置时钟分频因子,震荡器频率
0xA8, 0x3F, // 设置驱动路数
0xD3, 0x00, // 设置显示偏移
0x40, // 设置显示开始行 [5:0]
0x8D, 0x14, // 使能电荷泵
0x20, 0x00, // 水平寻址模式
0xA0 | 0x1, // 设置段重定义
0xC8, // 设置扫描方向
0xDA, 0x12, // 设置 COM 硬件引脚配置
0x81, 0xCF, // 设置对比度
0xD9, 0xF1, // 设置预充电周期
0xDB, 0x40, // 设置 VcomH 电压倍率
0xA4, // 全局显示开启
0xA6, // 设置显示方式: 正常显示
0xAF // 打开显示
};
/* 串口数据缓冲区 */
uint8_t uart_buf[128];
/* OLED 显示缓冲区 */
uint8_t oled_buf[1024];
/* 串口 DMA 发送完成标志 */
volatile uint8_t uart_dma_tx_complete = 0;
/* 串口 DMA 发送回调函数 */
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
uart_dma_tx_complete = 1;
}
/* OLED I2C 发送命令函数 */
void OLED_Send_Cmd(uint8_t cmd)
{
uint8_t data[2];
data[0] = 0x00; // Co = 0, D/C# = 0
data[1] = cmd;
while(HAL_I2C_Master_Transmit(&hi2c1, OLED_ADDR, data, sizeof(data), 1000) != HAL_OK);
}
/* OLED I2C 发送数据函数 */
void OLED_Send_Data(uint8_t *data, uint32_t size)
{
uint8_t buf[17];
buf[0] = 0x40; // Co = 0, D/C# = 1
while(size > 0)
{
uint32_t len = size > 16 ? 16 : size;
memcpy(&buf[1], data, len);
while(HAL_I2C_Master_Transmit(&hi2c1, OLED_ADDR, buf, len + 1, 1000) != HAL_OK);
data += len;
size -= len;
}
}
/* OLED 显示初始化函数 */
void OLED_Init()
{
HAL_Delay(100);
for(uint32_t i = 0; i < sizeof(OLED_Init_Cmd); i++)
{
OLED_Send_Cmd(OLED_Init_Cmd[i]);
}
}
/* OLED 显示清屏函数 */
void OLED_Clear()
{
memset(oled_buf, 0x00, sizeof(oled_buf));
}
/* OLED 显示字符函数 */
void OLED_Show_Char(uint8_t x, uint8_t y, char ch)
{
uint8_t *p = &oled_buf[x + y / 8 * OLED_WIDTH];
for(uint32_t i = 0; i < 8; i++)
{
if((font_8x16[(ch - ' ')*16 + i] & 0x80) != 0)
{
p[0] |= 0x01 << (y % 8);
}
else
{
p[0] &= ~(0x01 << (y % 8));
}
if((font_8x16[(ch - ' ')*16 + i] & 0x40) != 0)
{
p[1] |= 0x01 << (y % 8);
}
else
{
p[1] &= ~(0x01 << (y % 8));
}
p += OLED_WIDTH;
y++;
}
}
/* OLED 显示字符串函数 */
void OLED_Show_String(uint8_t x, uint8_t y, char *str)
{
while(*str != '\0')
{
OLED_Show_Char(x, y, *str);
x += 8;
str++;
}
}
/* 主函数 */
int main(void)
{
/* 初始化 HAL 库 */
HAL_Init();
/* 配置系统时钟 */
SystemClock_Config();
/* 配置 GPIO 串口1 */
MX_GPIO_Init();
MX_USART1_UART_Init();
/* 配置 GPIO I2C1 */
MX_GPIO_Init();
MX_I2C1_Init();
/* OLED 显示初始化 */
OLED_Init();
/* OLED 显示清屏 */
OLED_Clear();
/* 串口 DMA 发送 */
while(1)
{
sprintf((char*)uart_buf, "Hello World!\r\n");
uart_dma_tx_complete = 0;
HAL_UART_Transmit_DMA(&huart1, uart_buf, strlen((char*)uart_buf));
while(uart_dma_tx_complete == 0);
OLED_Show_String(0, 0, (char*)uart_buf);
OLED_Send_Data(oled_buf, sizeof(oled_buf));
HAL_Delay(1000);
}
}
```
这段代码实现了串口1在 DMA 模式下输出信息给 OLED,具体功能包括:
1. OLED 的初始化、清屏、字符和字符串显示等;
2. 串口1 的 DMA 发送;
3. 串口1 DMA 发送完成后将数据显示在 OLED 上。
需要注意的是,这段代码使用了字库文件 `font_8x16.c`,需要用户自己添加字库文件和相关函数。此外,涉及到的 HAL 库函数需要用户根据实际情况进行修改。
阅读全文