lijinlei 发表于 2024-7-4 07:31:34

手焊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


神农鼎 发表于 2024-7-4 07:57:52

学习,可以考虑改成
STC8H8K64U-45I-SOP16/TSSOP20
STC8H8K64U-45I-LQFP32/LQFP44/LQFP48/LQFP64
STC8H8K64U-45I-SKDIP28/PDIP40

这样资料多
深圳国芯人工智能有限公司-产品_STC8H系列 (stcai.com)





lijinlei 发表于 2024-7-4 08:08:11

神农鼎 发表于 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:24

你看下管脚图

lijinlei 发表于 2024-7-4 09:12:12

神农鼎 发表于 2024-7-4 08:12
你看下管脚图


STC15W408AS-TSSOP20管脚定义图如下

STC8H8K64U-TSSOP20管脚定义图如下




好像可以直接替换……
附PCB原理图


wangxiangtan 发表于 2024-7-4 14:41:42

老板不建议你用15W{:4_164:}
页: [1]
查看完整版本: 手焊STC15W408AS核心板及OLED动图播放