OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 6295|回复: 4

使用RT-Thread studio开启SPI框架驱动OLED

[复制链接]

33

主题

82

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
277
金钱
277
注册时间
2020-1-19
在线时间
94 小时
发表于 2021-9-8 09:43:17 | 显示全部楼层 |阅读模式
1金钱
想学习使用SPI框架驱动OLED,就准备把中景园的程序移植到RTT上,参考了网上的步骤,在settings里开启spi,在board.c里复制HAL_SPI_MspInit,在board.h和stm32xxxx_hal_config.h里开启了spi,然后代码如下:
  1. #include "OLED.h"

  2. #define RES_PIN  11
  3. #define DC_PIN   12
  4. #define CS_PIN   15
  5. uint8_t OLED_GRAM[128][8];

  6. static struct rt_spi_device* spi_dev_ssd1306; /* SPI设备ssd1306对象 */

  7. int oled_spi_device_init()
  8. {
  9.     __HAL_RCC_GPIOA_CLK_ENABLE();
  10.     //设备挂载到SPI总线,抽象为 spi10 设备,同时使用时还需进行 rt_spi_configure
  11.     rt_hw_spi_device_attach("spi1", "spi10", GPIOA, GPIO_PIN_15);
  12.     return RT_EOK;
  13. }
  14. INIT_DEVICE_EXPORT(oled_spi_device_init);//自动初始化

  15. int  my_oled_init(void)
  16. {
  17.     rt_pin_mode(RES_PIN, PIN_MODE_OUTPUT );
  18.     rt_pin_mode(DC_PIN, PIN_MODE_OUTPUT );
  19.     rt_pin_mode(CS_PIN, PIN_MODE_OUTPUT );

  20.     spi_dev_ssd1306 = (struct rt_spi_device *)rt_device_find("spi10");
  21.     if (!spi_dev_ssd1306)
  22.     {
  23.         rt_kprintf("spi sample run failed! can't find %s device!\n", "spi10");
  24.     }
  25.     else
  26.     {
  27.         // owner必须配置,因为默认为空,为空时无法进行初始化操作
  28.         spi_dev_ssd1306->bus->owner = spi_dev_ssd1306; // 必须!!!

  29.         // 配置spi
  30.         struct rt_spi_configuration cfg;
  31.         cfg.data_width = 8;
  32.         cfg.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB;  // 主机,模式0,高位在前
  33.         cfg.max_hz = 20 * 1000 * 1000; // SPI 接口时钟频率
  34.         rt_spi_configure(spi_dev_ssd1306, &cfg); // 此时才进行MspInit相关的时钟及IO口初始化
  35.     }
  36.     OLED_Init();
  37.     return RT_EOK;
  38. }

  39. //OLED写一个字节
  40. void OLED_WR_Byte(uint8_t dat, uint8_t cmd)
  41. {
  42.     if(cmd)
  43.     {
  44.         OLED_DC_Set();
  45.     }else{
  46.         OLED_DC_Clr();
  47.     }
  48.     rt_spi_send(spi_dev_ssd1306, &dat, 1);
  49.     OLED_DC_Set();
  50. }

  51. //开启OLED显示
  52. void OLED_DisPlay_On(void)
  53. {
  54.     OLED_WR_Byte(0x8D,OLED_CMD);//电荷泵使能
  55.     OLED_WR_Byte(0x14,OLED_CMD);//开启电荷泵
  56.     OLED_WR_Byte(0xAF,OLED_CMD);//点亮屏幕
  57. }

  58. //关闭OLED显示
  59. void OLED_DisPlay_Off(void)
  60. {
  61.     OLED_WR_Byte(0x8D,OLED_CMD);//电荷泵使能
  62.     OLED_WR_Byte(0x10,OLED_CMD);//关闭电荷泵
  63.     OLED_WR_Byte(0xAF,OLED_CMD);//关闭屏幕
  64. }

  65. //更新显存到OLED
  66. void OLED_Refresh(void)
  67. {
  68.     uint8_t i,n;
  69.     for(i=0;i<8;i++)
  70.     {
  71.        OLED_WR_Byte(0xb0+i,OLED_CMD); //设置行起始地址
  72.        OLED_WR_Byte(0x00,OLED_CMD);   //设置低列起始地址
  73.        OLED_WR_Byte(0x10,OLED_CMD);   //设置高列起始地址
  74.        for(n=0;n<128;n++)
  75.            OLED_WR_Byte(OLED_GRAM[n][i],OLED_DATA);
  76.   }
  77. }

  78. //清屏函数
  79. void OLED_Clear(void)
  80. {
  81.     uint8_t i,n;
  82.     for(i=0;i<8;i++)
  83.     {
  84.         for(n=0;n<128;n++)
  85.         {
  86.             OLED_GRAM[n][i]=0;//清除所有数据
  87.         }
  88.     }
  89.     OLED_Refresh();//更新显示
  90. }

  91. //画点
  92. //x:0~127
  93. //y:0~63
  94. void OLED_DrawPoint(uint8_t x,uint8_t y)
  95. {
  96.     uint8_t i,m,n;
  97.     i=y/8;
  98.     m=y%8;
  99.     n=1<<m;
  100.     OLED_GRAM[x][i]|=n;
  101. }

  102. //清除一个点
  103. //x:0~127
  104. //y:0~63
  105. void OLED_ClearPoint(uint8_t x,uint8_t y)
  106. {
  107.     uint8_t i,m,n;
  108.     i=y/8;
  109.     m=y%8;
  110.     n=1<<m;
  111.     OLED_GRAM[x][i]=~OLED_GRAM[x][i];
  112.     OLED_GRAM[x][i]|=n;
  113.     OLED_GRAM[x][i]=~OLED_GRAM[x][i];
  114. }

  115. //OLED的初始化
  116. void OLED_Init(void)
  117. {
  118.     OLED_RES_Clr();
  119.     rt_thread_delay(200);
  120.     OLED_RES_Set();

  121.     OLED_WR_Byte(0xAE,OLED_CMD);//--turn off oled panel
  122.     OLED_WR_Byte(0x00,OLED_CMD);//---set low column address
  123.     OLED_WR_Byte(0x10,OLED_CMD);//---set high column address
  124.     OLED_WR_Byte(0x40,OLED_CMD);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
  125.     OLED_WR_Byte(0x81,OLED_CMD);//--set contrast control register
  126.     OLED_WR_Byte(0xCF,OLED_CMD);// Set SEG Output Current Brightness
  127.     OLED_WR_Byte(0xA1,OLED_CMD);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
  128.     OLED_WR_Byte(0xC8,OLED_CMD);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
  129.     OLED_WR_Byte(0xA6,OLED_CMD);//--set normal display
  130.     OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
  131.     OLED_WR_Byte(0x3f,OLED_CMD);//--1/64 duty
  132.     OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset   Shift Mapping RAM Counter (0x00~0x3F)
  133.     OLED_WR_Byte(0x00,OLED_CMD);//-not offset
  134.     OLED_WR_Byte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency
  135.     OLED_WR_Byte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
  136.     OLED_WR_Byte(0xD9,OLED_CMD);//--set pre-charge period
  137.     OLED_WR_Byte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
  138.     OLED_WR_Byte(0xDA,OLED_CMD);//--set com pins hardware configuration
  139.     OLED_WR_Byte(0x12,OLED_CMD);
  140.     OLED_WR_Byte(0xDB,OLED_CMD);//--set vcomh
  141.     OLED_WR_Byte(0x40,OLED_CMD);//Set VCOM Deselect Level
  142.     OLED_WR_Byte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)
  143.     OLED_WR_Byte(0x02,OLED_CMD);//
  144.     OLED_WR_Byte(0x8D,OLED_CMD);//--set Charge Pump enable/disable
  145.     OLED_WR_Byte(0x14,OLED_CMD);//--set(0x10) disable
  146.     OLED_WR_Byte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)
  147.     OLED_WR_Byte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7)
  148.     OLED_WR_Byte(0xAF,OLED_CMD);
  149.     OLED_Clear();
  150.     OLED_DrawPoint(1, 2);
  151.     OLED_Refresh();
  152. }
复制代码
OLED_Init最后想画个点测试是否成功,但是屏幕没有点亮,msh里输入list_device可以看见spi1和spi10是正常开启的,请问是哪个步骤做错了吗

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

6

主题

889

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1460
金钱
1460
注册时间
2020-8-19
在线时间
332 小时
发表于 2021-9-8 09:52:39 | 显示全部楼层
回复

使用道具 举报

2

主题

594

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1458
金钱
1458
注册时间
2019-7-28
在线时间
137 小时
发表于 2021-9-8 10:23:14 | 显示全部楼层
可以直接去看看中景园原本的例程能不能点亮屏幕先
回复

使用道具 举报

33

主题

82

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
277
金钱
277
注册时间
2020-1-19
在线时间
94 小时
 楼主| 发表于 2021-9-8 10:33:56 | 显示全部楼层
lpwithv 发表于 2021-9-8 10:23
可以直接去看看中景园原本的例程能不能点亮屏幕先

可以的
回复

使用道具 举报

2

主题

594

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1458
金钱
1458
注册时间
2019-7-28
在线时间
137 小时
发表于 2021-9-8 10:38:36 | 显示全部楼层
不是很了解RTT,不过想这种一般SPI通信最好不要被打断,你可以看RTT是否有临界区这种东西,可以进临界区在进行SPI操做
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-6-10 15:39

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表