打印
[其他ST产品]

STM32 HAL 硬件IIC+DMA+简单图形库控制OLED

[复制链接]
1519|45
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
前言

本文将介绍在STM32 HAL库下实现硬件IIC+DMA控制0.96寸 OLED屏,以及OLED图形库的移植。



一、建立工程

平台:野火指南者STM32F103VET6 + STM32Cube MX + Keil MDK 5

(示例)
1.选择所用MCU。



使用特权

评论回复
沙发
wangtaohui|  楼主 | 2023-6-28 20:14 | 只看该作者
2.选择启用晶振

使用特权

评论回复
板凳
wangtaohui|  楼主 | 2023-6-28 20:14 | 只看该作者
3.选择Debug方式

使用特权

评论回复
地板
wangtaohui|  楼主 | 2023-6-28 20:14 | 只看该作者
4.设置时钟树

使用特权

评论回复
5
wangtaohui|  楼主 | 2023-6-28 20:15 | 只看该作者
5.选择合适的引脚开启I2C

使用特权

评论回复
6
wangtaohui|  楼主 | 2023-6-28 20:15 | 只看该作者
6.加入I2Cx_TX的DMA

使用特权

评论回复
7
wangtaohui|  楼主 | 2023-6-28 20:15 | 只看该作者
7.开启12Cx_event_interrupt

使用特权

评论回复
8
wangtaohui|  楼主 | 2023-6-28 20:15 | 只看该作者
8.配置完后建立工程

使用特权

评论回复
9
wangtaohui|  楼主 | 2023-6-28 20:16 | 只看该作者
二、编写和移植
本节主要介绍移植标准库编写的oledlib图形库过程。
oledlib库原作者:MjGame
原作例程开源地址:MjGame 的例程
本文使用的oledlib库修订者:一只程序缘
本文所要移植库的开源地址:一只程序缘 的例程

git clone https://gitee.com/jiezhuonew/oledlib.git
————————————————
版权声明:本文为CSDN博主「乙酸氧铍」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_44457994/article/details/114768659

使用特权

评论回复
10
wangtaohui|  楼主 | 2023-6-28 20:17 | 只看该作者
前期准备
1.先导入所需的文件
所用Delay文件参考《无需另配定时器在STM32 HAL下实现微秒级延时(兼容FreeRTOS)》



使用特权

评论回复
11
wangtaohui|  楼主 | 2023-6-28 20:17 | 只看该作者
2.将delay.h改为我们所用的Delay.h文件

使用特权

评论回复
12
wangtaohui|  楼主 | 2023-6-28 20:17 | 只看该作者
修改u16为unsigned short或uint16_t

使用特权

评论回复
13
wangtaohui|  楼主 | 2023-6-28 20:19 | 只看该作者
驱动部分修改
在oled_config.h中添加#include “main.h”,并修改TRANSFER_METHOD

使用特权

评论回复
14
wangtaohui|  楼主 | 2023-6-28 20:20 | 只看该作者
在oled_driver.h和oled_driver.c中注释掉标准库相关的东西:

使用特权

评论回复
15
wangtaohui|  楼主 | 2023-6-28 20:20 | 只看该作者
此时编译不再弹出错误。

使用特权

评论回复
16
wangtaohui|  楼主 | 2023-6-28 20:20 | 只看该作者
在oled_driver.c修改I2C_WriteByte函数
        /**
                 [url=home.php?mod=space&uid=247401]@brief[/url]  I2C_WriteByte,向OLED寄存器地址写一个byte的数据
                 @param  addr:寄存器地址
                                                 data:要写入的数据
                 @retval 无
        */
        void I2C_WriteByte(uint8_t addr, uint8_t data)
        {
//                while (I2C_GetFlagStatus(I2CX, I2C_FLAG_BUSY));

//                I2C_GenerateSTART(I2CX, ENABLE);//开启I2C1
//                while (!I2C_CheckEvent(I2CX, I2C_EVENT_MASTER_MODE_SELECT)); /*EV5,主模式*/

//                I2C_Send7bitAddress(I2CX, OLED_ADDRESS, I2C_Direction_Transmitter);//器件地址 -- 默认0x78
//                while (!I2C_CheckEvent(I2CX, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

//                I2C_SendData(I2CX, addr);//寄存器地址
//                while (!I2C_CheckEvent(I2CX, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

//                I2C_SendData(I2CX, data);//发送数据
//                while (!I2C_CheckEvent(I2CX, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

//                I2C_GenerateSTOP(I2CX, ENABLE);//关闭I2C1总线
                extern I2C_HandleTypeDef hi2c1;
                HAL_I2C_Mem_Write(&hi2c1, OLED_ADDRESS, addr, I2C_MEMADD_SIZE_8BIT, &data, 1, 10);
        }

使用特权

评论回复
17
wangtaohui|  楼主 | 2023-6-28 20:21 | 只看该作者
在oled_driver.c修改OLED_CLS函数
void OLED_CLS(void)//清屏
{
//        unsigned char m, n;
//        for (m = 0; m < 8; m++)
//        {
//                WriteCmd(0xb0 + m); //page0-page1
//                WriteCmd(0x00);   //low column start address
//                WriteCmd(0x10);   //high column start address
//                for (n = 0; n < 128; n++)
//                {
//                        WriteDat(0x00);
//                }
//        }

        extern unsigned char ScreenBuffer[SCREEN_PAGE_NUM][SCREEN_COLUMN];

    uint16_t i;
    for (i = 0; i < SCREEN_PAGE_NUM * SCREEN_COLUMN; ++i)
    {
        ScreenBuffer[0][i] = 0;
    }
        OLED_FILL(ScreenBuffer[0]);
}

使用特权

评论回复
18
wangtaohui|  楼主 | 2023-6-28 20:21 | 只看该作者
在oled_driver.c修改OLED_FILL函数
void OLED_FILL(unsigned char BMP[])
{
//        uint8_t i, j;
        unsigned char *p;
        p = BMP;

//        for (i = 0; i < 8; i++)
//        {
//                WriteCmd(0xb0 + i); //page0-page1
//                WriteCmd(0x00);   //low column start address
//                WriteCmd(0x10);

//                for (j = 0; j < 128; j++)
//                {
//                        WriteDat(*p++);
//                }
//        }
        extern I2C_HandleTypeDef hi2c1;
    while(hi2c1.State != HAL_I2C_STATE_READY);
    HAL_I2C_Mem_Write_DMA(&hi2c1, OLED_ADDRESS, 0x40, I2C_MEMADD_SIZE_8BIT, p, SCREEN_PAGE_NUM * SCREEN_PAGEDATA_NUM);
}

使用特权

评论回复
19
wangtaohui|  楼主 | 2023-6-28 20:22 | 只看该作者
注意到
//请将此函数放入1ms中断里,为图形提供时基
//系统时间基准主要用于FrameRateUpdateScreen()中固定帧率刷新屏幕
void OledTimeMsFunc(void)
{
        if(OledTimeMs != 0x00)
        {
                OledTimeMs--;
        }
}

使用特权

评论回复
20
wangtaohui|  楼主 | 2023-6-28 20:22 | 只看该作者
故到stm32f1xx_it.c中声明并添加此函数
若未使用FreeRTOS则在滴答定时器中断中添加,反之在对应定时器中断中添加:
/**
  * @brief This function handles System tick timer.
  */
void SysTick_Handler(void)
{
  /* USER CODE BEGIN SysTick_IRQn 0 */

  /* USER CODE END SysTick_IRQn 0 */
  HAL_IncTick();
  /* USER CODE BEGIN SysTick_IRQn 1 */
  OledTimeMsFunc();
  /* USER CODE END SysTick_IRQn 1 */
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

43

主题

482

帖子

0

粉丝