Arduino Uno 驱动OLED进阶 显示几何动画

本文介绍了一种使用Arduino和OLED显示屏绘制线条的方法。通过调整接线方式使其适用于IIC接口,并分享了完整的源代码及所需的库文件。示例程序能够绘制出随时间变化而变化的动态线条。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

这篇文章主要翻译国外某大神的作品

本示例可以学会如何画线条

 

先看看效果

 

YOUTUBE视频

https://www.youtube.com/watch?v=_t_lfcGV_YM

 

GITHUB  原代码地址

https://github.com/hwiguna/g33k/blob/master/ArduinoProjects/2015/_Done/099-Arduino_OLED_Display/HariChord/HariChord.ino  

以上代码包含SPI接线方式

 

本次略加修改为适合IIC的接线方式

接线方式请参考

Arduino 驱动OLED屏幕IIC接线方式简单入门

开源代码如下:

程序和库打包下载:https://u16460183.ctfile.com/fs/16460183-296052483

文件夹说明:

Adafruit_SSD1306-master —— OLED库

Adafruit-GFX-Library-master —— 图形库

LS_DrawForOLED —— 主程序

 

// HariChord, 2015
// Playing with OLED Display
// Big thanks to AdaFruit for providing the wonderful libraries!

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

#if (SSD1306_LCDHEIGHT != 64)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

int nFrames = 36;

void setup()   {                
  Serial.begin(9600);

  display.begin(SSD1306_SWITCHCAPVCC,0x3C);

  display.display();
  delay(1000);

  display.clearDisplay();
}


void loop() {
  for (int frame=0; frame < nFrames; frame++)
  {
    HariChord(frame);
  }

  for (int frame=(nFrames-1); frame >= 0; frame--)
  {
    HariChord(frame);
  }
}

void HariChord(int frame)
{
  display.clearDisplay();
  int n = 7;
  int r = frame * 64 / nFrames;
  float rot = frame * 2*PI / nFrames;
  for (int i=0; i<(n-1); i++)
  {
    float a = rot + i * 2*PI / n;
    int x1 = 64 + cos(a) * r;
    int y1 = 32 + sin(a) * r;
    for (int j=i+1; j<n; j++)
    {
      a = rot + j * 2*PI / n;
      int x2 = 64 + cos(a) * r;
      int y2 = 32 + sin(a) * r;
      display.drawLine(x1,y1, x2,y2, WHITE);
    }
  }
  display.display();
}

 

 

 

 

 

////////////////////////////////////////////////////////////////////////////////// //本程序只供学习使用,未经作者许可,不得用于其它任何用途 // // 文 件 名 : main.c // 版 本 号 : v2.0 // 作 者 : HuangKai // 生成日期 : 2019-3-19 // 最近修改 : // 功能描述 : arduino UNO OLED显示屏例程 // 说明: // ---------------------------------------------------------------- // GND 电源地 // VCC 5v电源 // D0 A5(SCL) // D1 A4(SDA) // RES A3 注:SPI接口显示屏改成IIC接口时需要接RES引脚 // IIC接口显示屏用户请忽略 // ---------------------------------------------------------------- // 修改历史 : // 日 期 : // 修改内容 : 创建文件 //版权所有,盗版必究。 //All rights reserved //******************************************************************************/ #include "oledfont.h" #include "Wire.h" #define res A3//RES #define OLED_RES_Clr() digitalWrite(res,LOW)//RES #define OLED_RES_Set() digitalWrite(res,HIGH) #define OLED_CMD 0 //写命令 #define OLED_DATA 1 //写数据 void setup() { uint8_t t=' '; OLED_Init(); OLED_ColorTurn(0);//0正常显示 1反色显示 OLED_DisplayTurn(0);//0正常显示 1翻转180度显示 while(1) { OLED_DrawBMP(0,0,128,64,BMP1); delay(500); OLED_Clear(); OLED_ShowChinese(0,0,0,16);//深 OLED_ShowChinese(18,0,1,16);//圳 OLED_ShowChinese(36,0,2,16);//旺 OLED_ShowChinese(54,0,3,16);//泓 OLED_ShowChinese(72,0,4,16);//科 OLED_ShowChinese(90,0,5,16);//技 //OLED_ShowChinese(108,0,6,16);//技 OLED_ShowString(8,2,"WANG HONG",16); OLED_ShowString(20,4,"2014/05/01",16); OLED_ShowString(0,6,"ASCII:",16); OLED_ShowString(63,6,"CODE:",16); OLED_ShowChar(48,6,t,16); t++; if(t>'~')t=' '; OLED_ShowNum(103,6,t,3,16); delay(500); OLED_Clear(); } } void loop() { } //反显函数 void OLED_ColorTurn(u8 i) { if(!i) OLED_WR_Byte(0xA6,OLED_CMD);//正常显示 else OLED_WR_Byte(0xA7,OLED_CMD);//反色显示 } //屏幕旋转180度 void OLED_DisplayTurn(u8 i) { if(i==0) { OLED_WR_Byte(0xC8,OLED_CMD);//正常显示 OLED_WR_Byte(0xA1,OLED_CMD); } else { OLED_WR_Byte(0xC0,OLED_CMD);//反转显示 OLED_WR_Byte(0xA0,OLED_CMD); } } //发送一个字节 //向SSD1306写入一个字节。 //mode:数据/命令标志 0,表示命令;1,表示数据; void OLED_WR_Byte(u8 dat,u8 mode) { Wire.beginTransmission(0x3c); if(mode){Wire.write(0x40);} else{Wire.write(0x00);} Wire.write(dat); // sends one byte Wire.endTransmission(); // stop transmitting } //坐标设置 void OLED_Set_Pos(u8 x, u8 y) { OLED_WR_Byte(0xb0+y,OLED_CMD); OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD); OLED_WR_Byte((x&0x0f),OLED_CMD); } //开启OLED显示 void OLED_Display_On(void) { OLED_WR_Byte(0X8D,OLED_CMD); //SET DCDC命令 OLED_WR_Byte(0X14,OLED_CMD); //DCDC ON OLED_WR_Byte(0XAF,OLED_CMD); //DISPLAY ON } //关闭OLED显示 void OLED_Display_Off(void) { OLED_WR_Byte(0X8D,OLED_CMD); //SET DCDC命令 OLED_WR_Byte(0X10,OLED_CMD); //DCDC OFF OLED_WR_Byte(0XAE,OLED_CMD); //DISPLAY OFF } //清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!! void OLED_Clear(void) { u8 i,n; for(i=0;i<8;i++) { OLED_WR_Byte (0xb0+i,OLED_CMD); //设置页地址(0~7) OLED_WR_Byte (0x00,OLED_CMD); //设置显示位置—列低地址 OLED_WR_Byte (0x10,OLED_CMD); //设置显示位置—列高地址 for(n=0;n<128;n++)OLED_WR_Byte(0,OLED_DATA); } //更新显示 } //在指定位置显示一个字符 //x:0~127 //y:0~63 //sizey:选择字体 6x8 8x16 void OLED_ShowChar(u8 x,u8 y,const u8 chr,u8 sizey) { u8 c=0,sizex=sizey/2,temp; u16 i=0,size1; if(sizey==8)size1=6; else size1=(sizey/8+((sizey%8)?1:0))*(sizey/2); c=chr-' ';//得到偏移后的值 OLED_Set_Pos(x,y); for(i=0;i<size1;i++) { if(i%sizex==0&&sizey!=8) OLED_Set_Pos(x,y++); if(sizey==8) { temp=pgm_read_byte(&asc2_0806[c][i]); OLED_WR_Byte(temp,OLED_DATA);//6X8字号 } else if(sizey==16) { temp=pgm_read_byte(&asc2_1608[c][i]); OLED_WR_Byte(temp,OLED_DATA);//8x16字号 } else return; } } //m^n函数 u32 oled_pow(u8 m,u8 n) { u32 result=1; while(n--)result*=m; return result; } //显示数字 //x,y :起点坐标 //num:要显示的数字 //len :数字的位数 //sizey:字体大小 void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 sizey) { u8 t,temp,m=0; u8 enshow=0; if(sizey==8)m=2; for(t=0;t<len;t++) { temp=(num/oled_pow(10,len-t-1))%10; if(enshow==0&&t<(len-1)) { if(temp==0) { OLED_ShowChar(x+(sizey/2+m)*t,y,' ',sizey); continue; }else enshow=1; } OLED_ShowChar(x+(sizey/2+m)*t,y,temp+'0',sizey); } } //显示一个字符号串 void OLED_ShowString(u8 x,u8 y,const char *chr,u8 sizey) { u8 j=0; while (chr[j]!='\0') { OLED_ShowChar(x,y,chr[j++],sizey); if(sizey==8)x+=6; else x+=sizey/2; } } //显示汉字 void OLED_ShowChinese(u8 x,u8 y,const u8 no,u8 sizey) { u16 i,size1=(sizey/8+((sizey%8)?1:0))*sizey; u8 temp; for(i=0;i<size1;i++) { if(i%sizey==0) OLED_Set_Pos(x,y++); if(sizey==16) { temp=pgm_read_byte(&Hzk[no][i]); OLED_WR_Byte(temp,OLED_DATA);//16x16字号 } // else if(sizey==xx) OLED_WR_Byte(xxx[c][i],OLED_DATA);//用户添加字号 else return; } } //显示图片 //x,y显示坐标 //sizex,sizey,图片长宽 //BMP:要显示的图片 void OLED_DrawBMP(u8 x,u8 y,u8 sizex, u8 sizey,const u8 BMP[]) { u16 j=0; u8 i,m,temp; sizey=sizey/8+((sizey%8)?1:0); for(i=0;i<sizey;i++) { OLED_Set_Pos(x,i+y); for(m=0;m<sizex;m++) { temp=pgm_read_byte(&BMP[j++]); OLED_WR_Byte(temp,OLED_DATA); } } } //OLED的初始化 void OLED_Init(void) { pinMode(res,OUTPUT);//RES Wire.begin(0x3c); // join i2c bus (address optional for master) OLED_RES_Clr(); delay(200); OLED_RES_Set(); OLED_WR_Byte(0xAE,OLED_CMD);//--turn off oled panel OLED_WR_Byte(0x00,OLED_CMD);//---set low column address OLED_WR_Byte(0x10,OLED_CMD);//---set high column address OLED_WR_Byte(0x40,OLED_CMD);//--set start line address Set Mapping RAM Display Start Line (0x00~0x3F) OLED_WR_Byte(0x81,OLED_CMD);//--set contrast control register OLED_WR_Byte(0xCF,OLED_CMD); // Set SEG Output Current Brightness OLED_WR_Byte(0xA1,OLED_CMD);//--Set SEG/Column Mapping 0xa0左右反置 0xa1正常 OLED_WR_Byte(0xC8,OLED_CMD);//Set COM/Row Scan Direction 0xc0上下反置 0xc8正常 OLED_WR_Byte(0xA6,OLED_CMD);//--set normal display OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64) OLED_WR_Byte(0x3f,OLED_CMD);//--1/64 duty OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset Shift Mapping RAM Counter (0x00~0x3F) OLED_WR_Byte(0x00,OLED_CMD);//-not offset OLED_WR_Byte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency OLED_WR_Byte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec OLED_WR_Byte(0xD9,OLED_CMD);//--set pre-charge period OLED_WR_Byte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock OLED_WR_Byte(0xDA,OLED_CMD);//--set com pins hardware configuration OLED_WR_Byte(0x12,OLED_CMD); OLED_WR_Byte(0xDB,OLED_CMD);//--set vcomh OLED_WR_Byte(0x40,OLED_CMD);//Set VCOM Deselect Level OLED_WR_Byte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02) OLED_WR_Byte(0x02,OLED_CMD);// OLED_WR_Byte(0x8D,OLED_CMD);//--set Charge Pump enable/disable OLED_WR_Byte(0x14,OLED_CMD);//--set(0x10) disable OLED_WR_Byte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5) OLED_WR_Byte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7) OLED_Clear(); OLED_WR_Byte(0xAF,OLED_CMD); /*display ON*/
05-27
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值