手焊STC15W408AS核心板及OLED动图播放
手动焊接PCB并实现OLED动图播放,效果如下attach://49964.mp4
细节
OLED 动图代码如下
/*----------------------------------------------------------------*/
#include "stc15.h"
#include "oled.h" //OLED引脚定义、控制函数
#include "bmp.h" //图片字模存放位置
int main(void)
{
OLED_Init(); //初始化OLED
OLED_ColorTurn(0); //0正常显示,1 反色显示
OLED_DisplayTurn(0); //0正常显示1 屏幕翻转显示
while(1)
{
OLED_DrawBMP(0,0,128,64,BMP1); //图片显示
delay_ms(10); //延时
//OLED_Clear(); //清屏
OLED_DrawBMP(0,0,128,64,BMP2);
delay_ms(10); //延时
//OLED_Clear(); //清屏
}
}
oled.c文件代码如下
#include "oled.h"
#include "oledfont.h"
//OLED的显存
//存放格式如下.
//0 1 2 3 ... 127
//0 1 2 3 ... 127
//0 1 2 3 ... 127
//0 1 2 3 ... 127
//0 1 2 3 ... 127
//0 1 2 3 ... 127
//0 1 2 3 ... 127
//0 1 2 3 ... 127
void delay_ms(unsigned int ms)//@24MHz
{
unsigned char data i, j;
while(ms--)
{
i = 24;
j = 85;
do
{
while (--j);
} while (--i);
}
return;
}
//反显函数
void OLED_ColorTurn(u8 i)
{
if(i==0)
{
OLED_WR_Byte(0xA6,OLED_CMD);//正常显示
}
if(i==1)
{
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);
}
if(i==1)
{
OLED_WR_Byte(0xC0,OLED_CMD);//反转显示
OLED_WR_Byte(0xA0,OLED_CMD);
}
}
//延时
void IIC_delay(void)
{
u8 t=1;
while(t--);
}
//起始信号
void I2C_Start(void)
{
OLED_SDA_Set();
OLED_SCL_Set();
IIC_delay();
OLED_SDA_Clr();
IIC_delay();
OLED_SCL_Clr();
}
//结束信号
void I2C_Stop(void)
{
OLED_SDA_Clr();
OLED_SCL_Set();
IIC_delay();
OLED_SDA_Set();
}
//等待信号响应
void I2C_WaitAck(void) //测数据信号的电平
{
OLED_SDA_Set();
IIC_delay();
OLED_SCL_Set();
IIC_delay();
OLED_SCL_Clr();
IIC_delay();
}
//写入一个字节
void Send_Byte(u8 dat)
{
u8 i;
for(i=0;i<8;i++)
{
OLED_SCL_Clr();//将时钟信号设置为低电平
if(dat&0x80)//将dat的8位从最高位依次写入
{
OLED_SDA_Set();
}
else
{
OLED_SDA_Clr();
}
IIC_delay();
OLED_SCL_Set();
IIC_delay();
OLED_SCL_Clr();
dat<<=1;
}
}
//发送一个字节
//向SSD1306写入一个字节。
//mode:数据 /命令标志 0,表示命令;1,表示数据;
void OLED_WR_Byte(u8 dat,u8 mode)
{
I2C_Start();
Send_Byte(0x78);
I2C_WaitAck();
if(mode){Send_Byte(0x40);}
else{Send_Byte(0x00);}
I2C_WaitAck();
Send_Byte(dat);
I2C_WaitAck();
I2C_Stop();
}
//坐标设置
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
}
/**
* @brief 清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!
* @retval 无
* @example OLED_Clear();
**/
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);
} //更新显示
}
/**
* @brief 显示一个字符,包括部分字符
* @param x 起始行位置 范围:0~127
* @param y 起始列位置 范围:0~7
* @param chr 要显示的单个字符,可显示字模库在 oledfont.h 文件
* @param sizey 要显示字体的大小,字号:8或者16
* @retval 无
* @example OLED_ShowChar(0,2,'A',16);
**/
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 sizey)
{
u8 c=0,sizex=sizey/2;
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) OLED_WR_Byte(asc2_0806,OLED_DATA);//6X8字号
else if(sizey==16) OLED_WR_Byte(asc2_1608,OLED_DATA);//8x16字号
// else if(sizey==xx) OLED_WR_Byte(asc2_xxxx,OLED_DATA);//用户添加字号
else return;
}
}
/**
* @brief求m的n次幂
**/
u32 oled_pow(u8 m,u8 n)
{
u32 result=1;
while(n--)result*=m;
return result;
}
/** ————————— 行(0~127)
* @brief OLED显示数字 -
* @param x 起始行位置 范围:0~127 -
* @param y 起始列位置 范围:0~7 -
* @param num 要显示的数字,范围:0~65535; -(从上到下是列(0~63))
同列显示超出5位需要更改行位置(否则显示数字会乱)。
如8号字体:OLED_ShowNum(0,0,65535,5,8); OLED_ShowNum(30,0,12345,5,8);可以一列同时显示 6553512345
* @param len 要显示数字的长度,范围:1~5
* @param sizey 要显示数字的大小,字号:8或者16
* @retval 无
* @example OLED_ShowNum(0,0,12345,5,16);
**/
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);
}
}
/**
* @brief 显示一个字符串
* @param x 起始行位置 范围:0~127
* @param y 起始列位置 范围:0~7
* @param *chr要显示的字符串,可显示字模库在 oledfont.h 文件
* @param sizey 要显示字体的大小,字号:8或者16
* @example OLED_ShowString(0,4,"ABB:",16);
**/
void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 sizey)
{
u8 j=0;
while (chr!='\0')
{
OLED_ShowChar(x,y,chr,sizey);
if(sizey==8)x+=6;
else x+=sizey/2;
}
}
/**
* @brief 显示汉字
* @param x 起始行位置 范围:0~127
* @param y 起始列位置 范围:0~7
* @param no 要显示的汉字排序号,0就是第一个,1就是第二个,以此类推...字模库在 oledfont.h 文件
* @param sizey 要显示字体的大小,字号:8或者16
* @example OLED_ShowChinese(18,0,1,16);
**/
void OLED_ShowChinese(u8 x,u8 y,u8 no,u8 sizey)
{
u16 i,size1=(sizey/8+((sizey%8)?1:0))*sizey;
for(i=0;i<size1;i++)
{
if(i%sizey==0) OLED_Set_Pos(x,y++);
if(sizey==16) OLED_WR_Byte(Hzk,OLED_DATA);//16x16字号
// else if(sizey==xx) OLED_WR_Byte(xxx,OLED_DATA);//用户添加字号
else return;
}
}
/**
* @brief 显示图片
* @param x 起始行位置 范围:0~127
* @param y 起始列位置 范围:0~7
* @param sizex图片的长
* @param sizey图片的宽
* @param BMP[]要显示的图片BMP1、BMP2、BMP3... 图片字模存放在 bmp.h 文件
* @example OLED_DrawBMP(30,0,69,64,BMP1);
**/
void OLED_DrawBMP(u8 x,u8 y,u8 sizex, u8 sizey,u8 BMP[])
{
u16 j=0;
u8 i,m;
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++)
{
OLED_WR_Byte(BMP,OLED_DATA);
}
}
}
/************************OLED初始化***********************/
void OLED_Init(void)
{
// OLED_RES_Clr(); //SPI接口显示屏改成IIC接口使用
// delay_ms(200);
// OLED_RES_Set();
OLED_WR_Byte(0xAE,OLED_CMD); //--关闭oled面板
OLED_WR_Byte(0x00,OLED_CMD); //--设置低列地址
OLED_WR_Byte(0x10,OLED_CMD); //--设置高列地址
OLED_WR_Byte(0x40,OLED_CMD); //--设置起始行地址设置映射RAM显示起始行 (0x00~0x3F)
OLED_WR_Byte(0x81,OLED_CMD); //--设置对比度控制寄存器
OLED_WR_Byte(0xCF,OLED_CMD); //--设置SEG输出电流亮度
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); //--设置正常显示
OLED_WR_Byte(0xA8,OLED_CMD); //--设置多路复用率(1 to 64)
OLED_WR_Byte(0x3f,OLED_CMD); //--1/64 duty
OLED_WR_Byte(0xD3,OLED_CMD); //--设置显示offset,移位映射RAM计数器 (0x00~0x3F)
OLED_WR_Byte(0x00,OLED_CMD); //--not offset
OLED_WR_Byte(0xd5,OLED_CMD); //--设置显示时钟分率/振荡频率
OLED_WR_Byte(0x80,OLED_CMD); //--设置分率, 设置时钟为100帧/秒
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); //--设置com引脚硬件配置
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); //-设置页面寻址方式 (0x00/0x01/0x02)
OLED_WR_Byte(0x02,OLED_CMD);
OLED_WR_Byte(0x8D,OLED_CMD); //--设置电荷泵使能/disable
OLED_WR_Byte(0x14,OLED_CMD); //--set(0x10) disable
OLED_WR_Byte(0xA4,OLED_CMD); // 禁用全部显示 (0xa4/0xa5)
OLED_WR_Byte(0xA6,OLED_CMD); // 禁用反转显示 (0xa6/a7)
OLED_Clear(); //OLED清屏
OLED_WR_Byte(0xAF,OLED_CMD); /*显示打开*/
}
代码详见附件。
PCB文件参考:https://oshwhub.com/wang0/stc15w408-kai-fa-ban_copy_copy
学习,可以考虑改成
STC8H8K64U-45I-SOP16/TSSOP20
STC8H8K64U-45I-LQFP32/LQFP44/LQFP48/LQFP64
STC8H8K64U-45I-SKDIP28/PDIP40
这样资料多
深圳国芯人工智能有限公司-产品_STC8H系列 (stcai.com)
神农鼎 发表于 2024-7-4 07:57
学习,可以考虑改成
STC8H8K64U-45I-SOP16/TSSOP20
STC8H8K64U-45I-LQFP32/LQFP44/LQFP48/LQFP64
STC8H8K64U-TSSOP20的引脚与STC15W408AS-TSSOP20定义相同吗?能不能直接替换?
这个PCB板我还有4个没焊接贴片元件,考虑直接换成STC8H8K64U那个,不知道能不能行,要不还得重新设计PCB,重新打板 你看下管脚图 神农鼎 发表于 2024-7-4 08:12
你看下管脚图
STC15W408AS-TSSOP20管脚定义图如下
STC8H8K64U-TSSOP20管脚定义图如下
好像可以直接替换……
附PCB原理图
老板不建议你用15W{:4_164:}
页:
[1]