Skip to content

C51

其中涉及到的一些知识点
  • delay

    延时函数:51 单片机的时钟频率为 12 MHz,转换成 Hz 就是 12×106 Hz,也就是一个时钟周期可以执行 12×106 次指令,那么一次指令的耗时就是

    112×106(s)

    而我们使用 delay(50000) ,花费的时间就是

    60000012×106(s)

    大概就是 50 毫秒(ms)

    600000 怎么来的

    while(t--) 循环需要 3 条指令: 加载 t 值、减 1、判断循环条件 因此 while(t--) 需要 12 个时钟周期 (3 个指令 x 4 个时钟周期) delay(50000) 中的循环需要执行 50000 次 所以总的时钟周期数 = 50000 x 12 = 600000

点灯

闪烁

c
#include <reg52.h>

// 用sbit来定义一个I/O口
// 至于为什么是P0^0,因为这个是固定的,不同的单片机是不同的,要看单片机文档
sbit LED = P0 ^ 0;

void delay(unsigned int t)
{
    while (t--);
}

void main(void)
{

    while (1) {
        // 将P0.0口赋值 0,该口电平为低,使LED亮
        // 如果想赋值 1为亮,则根据半导体性质,将LED灯反过来接即可
        // 下面代码每隔一段时间调整LED口的电压,实现闪烁功能
        LED = 0;
        delay(50000);
        LED = 1;
        delay(50000);
    }
}

流水灯

c
#include <reg52.h>

void delay(unsigned int t)
{
    while (t--);
}

void main(void)
{
    int i;
    while (1)
    {
        for (i = 0; i < 8; i++) {
            /**
            * 我们有8个LED灯,每次让一个LED灯亮,就是让该口的电压为0
            * 数字 1 的二进制为 00000001,对他取反就是 11111110,很轻松
            * 实现了一个灯的亮,1 左移1位的二进制是 00000010,取反就是
            * 11111101 实现了第二个的灯亮,以此类推实现流水灯
            */
            P0 = ~(1 << i);
            delay(5000);
        }
    }
}

蜂鸣器

蜂鸣器的一些知识点
  • 有源蜂鸣器只需要给他通电就可以发出声音,无源蜂鸣器需要输入对应的脉冲信号才能发出声音

  • 单片机提供的电流很小,可能不能使蜂鸣器正常工作,所以需要三极管允许更大的电流通过,使的蜂鸣器正常工作

按键控制蜂鸣器

c
#include <reg52.h>

sbit BUZZER = P0 ^ 0;
sbit KEY = P2 ^ 0;

void delay(unsigned int t)
{
    while (t--);
}

void main(void)
{
    while (1) {
        if (KEY == 0) {
            delay(20);
            if (KEY == 0) {
                BUZZER = ~BUZZER;
            }
        }
    }
}

选择有源蜂鸣器,将蜂鸣器的电压调整为 2V,打开电脑的声音,应该能听到蜂鸣器发出的声音

蜂鸣器播放音乐(生日快乐)

c
#include <reg52.h>

sbit BEEP = P0 ^ 0;

unsigned char code SONG_TONE[] = {212, 212, 190, 212, 159, 169, 212, 212, 190, 212, 142, 159, 212, 212, 106, 126, 129, 169, 190, 119, 119, 126, 159, 142, 159, 0};
unsigned char code SONG_LONG[] = {9, 3, 12, 12, 12, 24, 9, 3, 12, 12, 12, 24, 9, 3, 12, 12, 12, 12, 12, 9, 3, 12, 12, 12, 24, 0};

void delay(unsigned int t)
{
    while (t--);
}

void PlayMusic()
{
    unsigned int i = 0, j, k;
    while (SONG_LONG[i] != 0 || SONG_TONE[i] != 0) {
        for (j = 0; j < SONG_LONG[i] * 30; j++) {
            BEEP = ~BEEP;
            for (k = 0; k < SONG_TONE[i] / 3; k++);
        }
        delay(100);
        i++;
    }
}

void main()
{
    while (1) {
        PlayMusic();
        delay(5000);
    }
}

数码管

展示数字

我们选择的是共阳极数码管

c
#include <reg52.h>

void main(void)
{
    while (1) {
        P0 = 0xC0;
    }
}

根据需要选择对应的值来展示不同的数字

数字滚动

c
#include <reg52.h>

void delay(unsigned int t)
{
    while (t--);
}

int seg[10] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90};
void main(void)
{
    int i;
    while (1) {
        for (i = 0; i < 10; i++) {
            P0 = seg[i];
            delay(50000);
        }
    }
}

动态扫描

c
#include <reg52.h>

void delay(unsigned int t)
{
    while (t--);
}

int seg[10] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90};
void main(void)
{
    int i;
    int num;
    while (1) {
        num++;
        for (i = 0; i < 4; i++) {
            P2 = 1 << i;
            if (i == 0) {
                P0 = seg[num / 1000];
            } else if (i == 1) {
                P0 = seg[num % 1000 / 100];
            } else if (i == 2) {
                P0 = seg[num % 100 / 10];
            } else if (i == 3) {
                P0 = seg[num % 10];
            }
            /**
            * 刷新率在50Hz以上,人眼差不多就无法分辨出来了,所以延迟要
            * 少于某个阈值即可实现,500并非固定
            */
            delay(500);
            P0 = 0xff; // 消除拖影
        }
        if (num >= 9999) {
            num = 0;
        }
    }
}

点阵

c
#include <reg52.h>

unsigned char hang[8] = {0xFF, 0x99, 0x00, 0x00, 0x00, 0x81, 0xC3, 0xE7};
unsigned char lie[8]  = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};

void delay(unsigned int t)
{
    while (t--);
}
int main()
{
    while (1) {
        int i = 0;
        for (i = 0; i < 8; i++) {
            P2 = lie[i];
            P0 = hang[i];
            delay(300);
        }
    }
}

跳动的心

c
#include <reg52.h>

unsigned char hang[8] = {0xFF, 0x99, 0x00, 0x00, 0x00, 0x81, 0xC3, 0xE7};
unsigned char lie[8]  = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};

void delay(unsigned int t)
{
    while (t--);
}
int main()
{
    while (1) {
        int i = 0;
        for (i = 0; i < 8; i++) {
            P2 = lie[i];
            P0 = hang[i];
            delay(300);
        }
        P2 = 0x00;
        P0 = 0x00;
        delay(60000);
    }
}

按键

按键的一些知识点
  • 消抖

    独立按键为机械弹性开关,当按键的触点闭合,断开时,由于弹性作用,独立按键没有办法立刻保持稳定, 需要等待一定时间才能保持稳定,一般来说,这个抖动在 10 ~ 20ms 左右。

按键点灯

c
#include <reg52.h>

sbit LED = P0 ^ 0;
sbit KEY = P2 ^ 0;

void delay(unsigned int t)
{
    while (t--);
}

void main(void)
{
    while (1) {
        // 独立按键默认是高电平,即没有按下去为高电平,按下去为低电平。
        if (KEY == 0) { // 检测低电平,也就是按键是否按下
            delay(20);  // 消抖延时
            if (KEY == 0) {
                LED = ~LED;
                while (!LED); // 防误触,按下了长时间未松开则不处理(可以不写)
            }
        }
    }
}

按键实现数码管计数

c
#include <reg52.h>

sbit KEY = P3 ^ 0;

void delay(unsigned int t)
{
    while (t--);
}

int seg[10] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90};

void showSEG(int num)
{
    int i;
    for (i = 0; i < 2; i++) {
        P2 = 1 << i;
        if (i == 0) {
            P0 = seg[num / 10];
        } else if (i == 1) {
            P0 = seg[num % 10];
        }
        delay(500);
        P0 = 0xff;
    }
}
void main(void)
{
    int num = 0;
    while (1) {
        if (KEY == 0) {
            delay(20);
            if (KEY == 0) {
                if (num >= 99) {
                    num = 0;
                } else
                    num++;
                while (!KEY) {
                    showSEG(num);
                }
            }
        }
        showSEG(num);
    }
}

矩阵键盘

c
#include <reg52.h>

sbit L0 = P1 ^ 0;
sbit L1 = P1 ^ 1;
sbit L2 = P1 ^ 2;
sbit L3 = P1 ^ 3;

void delay(unsigned int t)
{
    while (t--);
}

int seg[16] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e};
int btn[4]  = {0xef, 0xdf, 0xbf, 0x7f};

void showSEG(int num)
{
    int i;
    for (i = 0; i < 2; i++) {
        P2 = 1 << i;
        if (i == 0) {
            P0 = seg[num / 10];
        } else if (i == 1) {
            P0 = seg[num % 10];
        }
        delay(500);
        P0 = 0xff;
    }
}
void main(void)
{
    int num = 0;
    int i, j;
    while (1) {
        for (i = 0; i < 4; i++) {
            P1 = btn[i];
            for (j = 0; j < 4; j++) {
                if (L0 == 0) num = i * 4 + 1;
                if (L1 == 0) num = i * 4 + 2;
                if (L2 == 0) num = i * 4 + 3;
                if (L3 == 0) num = i * 4 + 4;
            }
            showSEG(num);
            delay(500);
        }
    }
}

定时器

c
#include <reg52.h>

sbit LED = P0 ^ 0;

void time0_init(void)
{
    // 工作模式:GATE=0;C/T=0;M1=0,M0=1
    TMOD |= 0x01;
    // 初始值
    TH0 = 0xfc;
    TL0 = 0x18;
    // 启动定时器
    TR0 = 1;
}

void main(void)
{
    time0_init();
    while (1);
}

具体效果可以查看下方的 中断和定时器的结合 部分。

中断

中断的一些知识点
符号描述说明具体描述
EA中断总开关1 时 CPU 开放 中断,为 0 时 CPU 屏蔽 所有中断申请
EX0外部中断1允许 外部中断,为 0禁止 外部中断见下方 EX0
IT0外部中断 0 触发方式选择位1 时下降沿触发,为 0 时低电平触发

EX0

  • (此处为外部中断 0,还有其余的中断例如 EX1, ET0, ET1, ES) (ET0/ET1): 定时器中断 (ES): 串口中断

interrupt 0

  • 这里不是 C 基础语法,属于嵌入式的语法,用于处理中断 0,当中断 0 触发时,执行的函数

所以触发中断只需给对应的寄存器赋值,例如

c
EA = 1;
EX0 = 1;
IT0 = 1;

执行完成后,会触发 interrupt 0 声明的函数,即 abc

c
void abc() interrupt 0 {

}

中断实现按键点灯

c
#include <reg52.h>

sbit LED = P0 ^ 0;
sbit KEY = P3 ^ 2;

void it0_init()
{
    EA  = 1; // 总中断开
    EX0 = 1; // IT0中断开
    IT0 = 1; // TCON中控制INT0触发方式位,INT0下降沿触发中断
}

void it0_isr() interrupt 0
{
    if (KEY == 0) LED = !LED;
}

void main(void)
{
    it0_init(); // 中断初始化
    while (1);
}

中断和定时器的结合

之前使用 delay 延时来进行 LED 灯的闪烁,这次我们通过更加精确的定时器来实现闪烁

c
#include <reg52.h>

sbit LED = P0 ^ 0;

void time0_init(void)
{
    // 工作模式:GATE=0;C/T=0;M1=0,M0=1
    TMOD |= 0x01;
    // 初始值
    TH0 = 0xfc;
    TL0 = 0x18;
    // 启动中断
    EA  = 1;
    ET0 = 1;
    // 启动定时器
    TR0 = 1;
}

void time0() interrupt 1
{
    static unsigned short i = 0;
    // 初始化
    TH0 = 0xfc;
    TL0 = 0x18;

    i++;
    if (i == 500) {
        i   = 0;
        LED = !LED;
    }
}

void main(void)
{
    time0_init();
    while (1);
}

火灾报警器(对温度、光亮等敏感)

I2C 总线

I2C 总线的一些知识点

更多信息

符号描述说明具体描述
SCL时钟线
SDA数据线
  • 开始 : SCL 为高电平的时候,SDA 由高电平变为低电平,开始传送数据
  • 结束 : SCL 为高电平的时候,SDA 由低电平变为高电平,停止传输数据
  • 应答 : 接收者收到 8bit 数据后,向发送者发出低电平脉冲,表示收到数据

实现 I2C 通信

c
#include <reg52.h>

#define SDA P1 ^ 0
#define SCL P1 ^ 1

#define DEV_ADDR  0x78
#define DATA_MODE 0x40
#define CMD_MODE  0x00

void delay(unsigned int t)
{
    while (t--);
}

// 发送起始信号
void Dri_IIC_Start()
{
    SCL = 1;
    SDA = 1;
    SDA = 0;
    SCL = 0;
}

// 发送结束信号
void Dri_IIC_Stop()
{
    SDA = 0;
    SCL = 1;
    SDA = 1;
}

// 发送一个字节
void Dri_IIC_SendByte(unsigned char byte)
{
    unsigned char i;
    for (i = 0; i < 8; i++) {
        SDA = (byte & (0x80 >> i)) == 0 ? 0 : 1;
        SCL = 1;
        SCL = 0;
    }
}

// 接收一个字节
unsigned char Dri_IIC_ReceiveByte()
{
    unsigned char byte = 0;
    unsigned char i;
    SDA = 1;
    for (i = 0; i < 8; i++) {
        SCL  = 1;
        byte = (byte << 1) | SDA;
        SCL  = 0;
    }
    return byte;
}

// 接收确认信号
bit Dri_IIC_ReceiveAck()
{
    bit ack;
    SDA = 1;
    SCL = 1;
    ack = SDA;
    SCL = 0;
    return ack;
}

// 发送确认信号
void Dri_IIC_SendAck(bit ack)
{
    SDA = ack;
    SCL = 1;
    SCL = 0;
}

void main()
{
    unsigned char code Data[] = "abcdefghABCDEFGH";
    while (1){
        Dri_IIC_Start();
        Dri_IIC_SendByte(DEV_ADDR);
        Dri_IIC_ReceiveAck();
        Dri_IIC_SendByte(DATA_MODE);
        Dri_IIC_ReceiveAck();
        for (i = 0; i < 16; i++) {
            Dri_IIC_SendByte(Data[i]);
            Dri_IIC_ReceiveAck();
        }
        Dri_IIC_Stop();
    }
}

具体效果可以查看下方的 OLED 部分。

串口通信

串口通信的一些知识点
  • 使用 sscome 来进行串口收发数据进行调试下载地址

实现 串口通信

c
#include <reg52.h>

unsigned char UartBuf = 0;

void SendStr(unsigned char *p);
void SendOneByte(unsigned char c);

void UsartInit()
{
    SCON = 0x50;      // 串口工作方式1,接收数据
    TMOD = 0x20;      // 定时器T1工作方式2
    TH1 = TL1 = 0xF3; // 芯片频率为12MHz, 设置波特率为2400,在SMOD作用下加倍,4800
    PCON      = 0x80; // 波特率加倍

    EA = 1; // 打开CPU中断允许位
    ES = 1; // 打开串口中断允许位

    TR1 = 1; // 启动计时器1
}
void main()
{
    UsartInit();
    while (1) {
        if (UartBuf) {
            SendStr("Hello, world!\r\n");
            UartBuf = 0;
        }
    }
}

void ReceiveDat() interrupt 4
{
    if (RI) {
        RI      = 0;
        UartBuf = SBUF;
    } else
        TI = 0;
}

void SendOneByte(unsigned char c)
{
    SBUF = c;
    while (!TI);
    TI = 0;
}

void SendStr(unsigned char *p)
{

    while (*p != '\0') {
        SendOneByte(*p);
        p++;
    }
}

波特率为 4800,芯片频率用的 12MHz

LCD 显示屏

其中涉及到的一些知识点

更多信息

符号描述说明具体描述
VSS电源地接地
VDD电源正极接电源正极
VEE/VL液晶显示偏压信号接地,也可以接一个滑动变阻器来控制亮度
RS数据/命令选择1 时传 数据,为 0 时传 命令见下方 RS
RW读/写选择1,为 0
E使能信号0 时 显示屏工作,为 1 时 停止工作
D0 ~ D7数据显示的字符见下方 编码

RS

  • RS 信号决定了当前的操作是 数据 传送还是 命令 传送,其中传 数据 是指显示屏上显示什么字符,传 命令 是指在哪显示。

编码

  • 显示字符时,需要将字符转换为对应的二进制数,然后通过 D0D7 输出。字模编码见下图,低四位为横坐标,高四位为纵坐标。

指令表

注意

下面的代码中我们的数据 Data 首末尾都有三个空字符,所以在 LCD_Write_Cmd 写入 0x00 如果去除掉 Data 的空格,那么更改为 0x03 即可.

为什么要加 0x80 ?

  • 在指令集中,所有的指令都有一位是 1LCD1602 就是用他来区分是哪一条指令的,其中 指令 8 就是第七位为 1,所以加上 0x80 就是在屏幕 第一行第一个位置显示字符以此类推,即可控制在哪显示。
c
void main()
{
    unsigned char code Data[] = "   I Love You   "; // "I Love You   "

    unsigned char i;

    LCD_Init();

    LCD_Write_Cmd(0x00 + 0x80); // LCD_Write_Cmd(0x03 + 0x80)
    for (i = 0; i < 16; i++) {
        LCD_Write_Data(Data[i]);
    }
    while (1);
}

显示字符

c
#include <reg52.h>

#define LCD_Data P0

sbit LCD_RS = P2 ^ 0;
sbit LCD_RW = P2 ^ 1;
sbit LCD_E  = P2 ^ 2;

void delay(unsigned int t)
{
    while (t--);
}

void main()
{
    unsigned char code Data[] = "   I Love You   "; // 第一行显示,共十六个字符

    unsigned char i;

    LCD_Init(); // LCD1602 初始化

    LCD_Write_Cmd(0x00 + 0x80); // 第一行第一列地址,0x00 可以省去
    for (i = 0; i < 16; i++) {
        LCD_Write_Data(Data[i]);
    }
    while (1);
}
c
// 初始化
void LCD_Init()
{
    LCD_Write_Cmd(0x01); // 指令1 ——清屏
    LCD_Write_Cmd(0x06); // 指令3 ——AC加1,画面不动
    LCD_Write_Cmd(0x0c); // 指令4 ——显示开,光标关,闪烁关
    LCD_Write_Cmd(0x38); // 指令6 ——8位数据接口,两行显示,5X7点阵
    LCD_Write_Cmd(0x80); // 指令8 ——从第一行第一列开始显示
}
c
// 写命令
void LCD_Write_Cmd(unsigned char Cmd)
{

    LCD_Check_Busy(); // 判忙

    LCD_RS = 0; // 0 指令
    LCD_RW = 0; // 0 写

    LCD_E    = 0;
    LCD_Data = Cmd; // 送指令
    delay(1000);

    LCD_E = 1; // 拉高
    delay(1000);

    LCD_E = 0;
}
c
// 写数据
void LCD_Write_Data(unsigned char Data)
{

    LCD_Check_Busy(); // 判忙

    LCD_RS = 1; // 1 数据
    LCD_RW = 0; // 0 写

    LCD_E    = 0;
    LCD_Data = Data; // 送数据
    delay(1000);

    LCD_E = 1; // 拉高
    delay(1000);

    LCD_E = 0;
}
c
// 忙检测
void LCD_Check_Busy()
{

    unsigned char temp;

    LCD_Data = 0xff; // 十六进制:1111 1111
    LCD_RS   = 0;    // 0 指令
    LCD_RW   = 1;    // 1 读

    do {
        LCD_E = 1;        // 拉高
        temp  = LCD_Data; // 将 LCD 状态保存在 temp 中,用于判忙
        LCD_E = 0;        // 负跳变使能
    } while (temp & 0x80); // 结果为 1,LCD 忙,继续循环;结果为 0,LCD 不忙,可以进行后面的操作
}

因为使用的是 P0 口,所以需要右下角的上拉电阻,如果使用别的口,则不需要。

显示两行字符

扩展方法
c
/**
 * @brief 设置光标位置
 * @param  Line 行位置,范围:1~2
 * @param  Column 列位置,范围:1~16
 * @retval
 */
void LCD_SetCursor(unsigned char Line, unsigned char Column)
{
    if (Line == 1) {
        LCD_Write_Cmd(0x80 | (Column - 1));
    } else if (Line == 2) {
        LCD_Write_Cmd(0x80 | (Column - 1 + 0x40));
    }
}
/**
 * @brief  返回值: X的Y次方
 */
int LCD_Pow(int X, int Y)
{
    unsigned char i;
    int Result = 1;
    for (i = 0; i < Y; i++) {
        Result *= X;
    }
    return Result;
}
/**
 * @brief  在LCD1602指定位置开始显示所给数字
 * @param  Line 起始行位置,范围:1~2
 * @param  Column 起始列位置,范围:1~16
 * @param  Number 要显示的数字,范围:0~65535
 * @param  Length 要显示数字的长度,范围:1~5
 * @retval
 */
void LCD_ShowNum(unsigned char Line, unsigned char Column, unsigned int Number, unsigned char Length)
{
    unsigned char i;
    LCD_SetCursor(Line, Column);
    for (i = Length; i > 0; i--) {
        LCD_Write_Data(Number / LCD_Pow(10, i - 1) % 10 + '0');
    }
}
/**
 * @brief  在LCD1602指定位置开始显示所给字符串
 * @param  Line 起始行位置,范围:1~2
 * @param  Column 起始列位置,范围:1~16
 * @param  String 要显示的字符串
 * @retval
 */
void LCD_ShowString(unsigned char Line, unsigned char Column, char *String)
{
    unsigned char i;
    LCD_SetCursor(Line, Column);
    for (i = 0; String[i] != '\0'; i++) {
        LCD_Write_Data(String[i]);
    }
}

这时候可以这样显示两行字符:

c
void main()
{
    LCD_Init();
    while (1) {
        LCD_ShowString(1, 1, "   I Love You   ");
        LCD_ShowString(2, 1, "abcdefghigklmnopqRSTuvwxyz"); // 显示时
    }
}
c
void main()
{
    unsigned char code Data_1[] = "   I Love You   "; // 第一行显示
    unsigned char code Data_2[] = "abcdefghABCDEFGH"; // 第二行显示

    unsigned char i;

    LCD_Init(); // LCD1602 初始化

    LCD_Write_Cmd(0x00 + 0x80); // 第一行第一列地址,0x00 可以省去
    for (i = 0; i < 16; i++) {
        LCD_Write_Data(Data_1[i]);
    }

    LCD_Write_Cmd(0x40 + 0x80); // 第二行第一列地址
    for (i = 0; i < 16; i++) {
        LCD_Write_Data(Data_2[i]);
    }

    while (1);
}

画面移动

c
void main()
{
    unsigned char code Data[] = "abcdefghigklmnopqrstuvwxyz";

    unsigned char i;

    LCD_Init(); // LCD1602 初始化

    LCD_Write_Cmd(0x00 + 0x80); // 第一行第一列地址,0x00 可以省去
    for (i = 0; i < 26; i++) {
        LCD_Write_Data(Data[i]);
    }

    while (1) {
        delay(500000);       // 控制移动速度
        LCD_Write_Cmd(0x18); // 指令5 ——画面左移一个字符位,光标不动
    }
}

OLED 显示屏

其中涉及到的一些知识点

更多信息

符号描述说明具体描述
SCL时钟线
SDA数据线
GND电源地接地
VCC电源正极接电源正极

OLED 采用 I2C 总线进行传输,其余代码去 I2C 模块寻找

显示字符

对应的字符集
c
const unsigned char code OLED_Font[][16] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //  0

    0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x33, 0x30, 0x00, 0x00, 0x00, //! 1

    0x00, 0x10, 0x0C, 0x06, 0x10, 0x0C, 0x06, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //" 2

    0x40, 0xC0, 0x78, 0x40, 0xC0, 0x78, 0x40, 0x00,
    0x04, 0x3F, 0x04, 0x04, 0x3F, 0x04, 0x04, 0x00, // # 3

    0x00, 0x70, 0x88, 0xFC, 0x08, 0x30, 0x00, 0x00,
    0x00, 0x18, 0x20, 0xFF, 0x21, 0x1E, 0x00, 0x00, //$ 4

    0xF0, 0x08, 0xF0, 0x00, 0xE0, 0x18, 0x00, 0x00,
    0x00, 0x21, 0x1C, 0x03, 0x1E, 0x21, 0x1E, 0x00, //% 5

    0x00, 0xF0, 0x08, 0x88, 0x70, 0x00, 0x00, 0x00,
    0x1E, 0x21, 0x23, 0x24, 0x19, 0x27, 0x21, 0x10, //& 6

    0x10, 0x16, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //' 7

    0x00, 0x00, 0x00, 0xE0, 0x18, 0x04, 0x02, 0x00,
    0x00, 0x00, 0x00, 0x07, 0x18, 0x20, 0x40, 0x00, //( 8

    0x00, 0x02, 0x04, 0x18, 0xE0, 0x00, 0x00, 0x00,
    0x00, 0x40, 0x20, 0x18, 0x07, 0x00, 0x00, 0x00, //) 9

    0x40, 0x40, 0x80, 0xF0, 0x80, 0x40, 0x40, 0x00,
    0x02, 0x02, 0x01, 0x0F, 0x01, 0x02, 0x02, 0x00, //* 10

    0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00,
    0x01, 0x01, 0x01, 0x1F, 0x01, 0x01, 0x01, 0x00, //+ 11

    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x80, 0xB0, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, //, 12

    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, //- 13

    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, //. 14

    0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x18, 0x04,
    0x00, 0x60, 0x18, 0x06, 0x01, 0x00, 0x00, 0x00, /// 15

    0x00, 0xE0, 0x10, 0x08, 0x08, 0x10, 0xE0, 0x00,
    0x00, 0x0F, 0x10, 0x20, 0x20, 0x10, 0x0F, 0x00, // 0 16

    0x00, 0x10, 0x10, 0xF8, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // 1 17

    0x00, 0x70, 0x08, 0x08, 0x08, 0x88, 0x70, 0x00,
    0x00, 0x30, 0x28, 0x24, 0x22, 0x21, 0x30, 0x00, // 2 18

    0x00, 0x30, 0x08, 0x88, 0x88, 0x48, 0x30, 0x00,
    0x00, 0x18, 0x20, 0x20, 0x20, 0x11, 0x0E, 0x00, // 3 19

    0x00, 0x00, 0xC0, 0x20, 0x10, 0xF8, 0x00, 0x00,
    0x00, 0x07, 0x04, 0x24, 0x24, 0x3F, 0x24, 0x00, // 4 20

    0x00, 0xF8, 0x08, 0x88, 0x88, 0x08, 0x08, 0x00,
    0x00, 0x19, 0x21, 0x20, 0x20, 0x11, 0x0E, 0x00, // 5 21

    0x00, 0xE0, 0x10, 0x88, 0x88, 0x18, 0x00, 0x00,
    0x00, 0x0F, 0x11, 0x20, 0x20, 0x11, 0x0E, 0x00, // 6 22

    0x00, 0x38, 0x08, 0x08, 0xC8, 0x38, 0x08, 0x00,
    0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, // 7 23

    0x00, 0x70, 0x88, 0x08, 0x08, 0x88, 0x70, 0x00,
    0x00, 0x1C, 0x22, 0x21, 0x21, 0x22, 0x1C, 0x00, // 8 24

    0x00, 0xE0, 0x10, 0x08, 0x08, 0x10, 0xE0, 0x00,
    0x00, 0x00, 0x31, 0x22, 0x22, 0x11, 0x0F, 0x00, // 9 25

    0x00, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, //: 26

    0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x80, 0x60, 0x00, 0x00, 0x00, 0x00, //; 27

    0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x00,
    0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, //< 28

    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00,
    0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, //= 29

    0x00, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00,
    0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, //> 30

    0x00, 0x70, 0x48, 0x08, 0x08, 0x08, 0xF0, 0x00,
    0x00, 0x00, 0x00, 0x30, 0x36, 0x01, 0x00, 0x00, //? 31

    0xC0, 0x30, 0xC8, 0x28, 0xE8, 0x10, 0xE0, 0x00,
    0x07, 0x18, 0x27, 0x24, 0x23, 0x14, 0x0B, 0x00, //@ 32

    0x00, 0x00, 0xC0, 0x38, 0xE0, 0x00, 0x00, 0x00,
    0x20, 0x3C, 0x23, 0x02, 0x02, 0x27, 0x38, 0x20, // A 33

    0x08, 0xF8, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00,
    0x20, 0x3F, 0x20, 0x20, 0x20, 0x11, 0x0E, 0x00, // B 34

    0xC0, 0x30, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00,
    0x07, 0x18, 0x20, 0x20, 0x20, 0x10, 0x08, 0x00, // C 35

    0x08, 0xF8, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00,
    0x20, 0x3F, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x00, // D 36

    0x08, 0xF8, 0x88, 0x88, 0xE8, 0x08, 0x10, 0x00,
    0x20, 0x3F, 0x20, 0x20, 0x23, 0x20, 0x18, 0x00, // E 37

    0x08, 0xF8, 0x88, 0x88, 0xE8, 0x08, 0x10, 0x00,
    0x20, 0x3F, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, // F 38

    0xC0, 0x30, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00,
    0x07, 0x18, 0x20, 0x20, 0x22, 0x1E, 0x02, 0x00, // G 39

    0x08, 0xF8, 0x08, 0x00, 0x00, 0x08, 0xF8, 0x08,
    0x20, 0x3F, 0x21, 0x01, 0x01, 0x21, 0x3F, 0x20, // H 40

    0x00, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x00, 0x00,
    0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // I 41

    0x00, 0x00, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x00,
    0xC0, 0x80, 0x80, 0x80, 0x7F, 0x00, 0x00, 0x00, // J 42

    0x08, 0xF8, 0x88, 0xC0, 0x28, 0x18, 0x08, 0x00,
    0x20, 0x3F, 0x20, 0x01, 0x26, 0x38, 0x20, 0x00, // K 43

    0x08, 0xF8, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x20, 0x3F, 0x20, 0x20, 0x20, 0x20, 0x30, 0x00, // L 44

    0x08, 0xF8, 0xF8, 0x00, 0xF8, 0xF8, 0x08, 0x00,
    0x20, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x20, 0x00, // M 45

    0x08, 0xF8, 0x30, 0xC0, 0x00, 0x08, 0xF8, 0x08,
    0x20, 0x3F, 0x20, 0x00, 0x07, 0x18, 0x3F, 0x00, // N 46

    0xE0, 0x10, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00,
    0x0F, 0x10, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x00, // O 47

    0x08, 0xF8, 0x08, 0x08, 0x08, 0x08, 0xF0, 0x00,
    0x20, 0x3F, 0x21, 0x01, 0x01, 0x01, 0x00, 0x00, // P 48

    0xE0, 0x10, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00,
    0x0F, 0x18, 0x24, 0x24, 0x38, 0x50, 0x4F, 0x00, // Q 49

    0x08, 0xF8, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00,
    0x20, 0x3F, 0x20, 0x00, 0x03, 0x0C, 0x30, 0x20, // R 50

    0x00, 0x70, 0x88, 0x08, 0x08, 0x08, 0x38, 0x00,
    0x00, 0x38, 0x20, 0x21, 0x21, 0x22, 0x1C, 0x00, // S 51

    0x18, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x18, 0x00,
    0x00, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x00, 0x00, // T 52

    0x08, 0xF8, 0x08, 0x00, 0x00, 0x08, 0xF8, 0x08,
    0x00, 0x1F, 0x20, 0x20, 0x20, 0x20, 0x1F, 0x00, // U 53

    0x08, 0x78, 0x88, 0x00, 0x00, 0xC8, 0x38, 0x08,
    0x00, 0x00, 0x07, 0x38, 0x0E, 0x01, 0x00, 0x00, // V 54

    0xF8, 0x08, 0x00, 0xF8, 0x00, 0x08, 0xF8, 0x00,
    0x03, 0x3C, 0x07, 0x00, 0x07, 0x3C, 0x03, 0x00, // W 55

    0x08, 0x18, 0x68, 0x80, 0x80, 0x68, 0x18, 0x08,
    0x20, 0x30, 0x2C, 0x03, 0x03, 0x2C, 0x30, 0x20, // X 56

    0x08, 0x38, 0xC8, 0x00, 0xC8, 0x38, 0x08, 0x00,
    0x00, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x00, 0x00, // Y 57

    0x10, 0x08, 0x08, 0x08, 0xC8, 0x38, 0x08, 0x00,
    0x20, 0x38, 0x26, 0x21, 0x20, 0x20, 0x18, 0x00, // Z 58

    0x00, 0x00, 0x00, 0xFE, 0x02, 0x02, 0x02, 0x00,
    0x00, 0x00, 0x00, 0x7F, 0x40, 0x40, 0x40, 0x00, //[ 59

    0x00, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x01, 0x06, 0x38, 0xC0, 0x00, //\ 60

    0x00, 0x02, 0x02, 0x02, 0xFE, 0x00, 0x00, 0x00,
    0x00, 0x40, 0x40, 0x40, 0x7F, 0x00, 0x00, 0x00, //] 61

    0x00, 0x00, 0x04, 0x02, 0x02, 0x02, 0x04, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //^ 62

    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, //_ 63

    0x00, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //` 64

    0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
    0x00, 0x19, 0x24, 0x22, 0x22, 0x22, 0x3F, 0x20, // a 65

    0x08, 0xF8, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00,
    0x00, 0x3F, 0x11, 0x20, 0x20, 0x11, 0x0E, 0x00, // b 66

    0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00,
    0x00, 0x0E, 0x11, 0x20, 0x20, 0x20, 0x11, 0x00, // c 67

    0x00, 0x00, 0x00, 0x80, 0x80, 0x88, 0xF8, 0x00,
    0x00, 0x0E, 0x11, 0x20, 0x20, 0x10, 0x3F, 0x20, // d 68

    0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
    0x00, 0x1F, 0x22, 0x22, 0x22, 0x22, 0x13, 0x00, // e 69

    0x00, 0x80, 0x80, 0xF0, 0x88, 0x88, 0x88, 0x18,
    0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // f 70

    0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00,
    0x00, 0x6B, 0x94, 0x94, 0x94, 0x93, 0x60, 0x00, // g 71

    0x08, 0xF8, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00,
    0x20, 0x3F, 0x21, 0x00, 0x00, 0x20, 0x3F, 0x20, // h 72

    0x00, 0x80, 0x98, 0x98, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // i 73

    0x00, 0x00, 0x00, 0x80, 0x98, 0x98, 0x00, 0x00,
    0x00, 0xC0, 0x80, 0x80, 0x80, 0x7F, 0x00, 0x00, // j 74

    0x08, 0xF8, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00,
    0x20, 0x3F, 0x24, 0x02, 0x2D, 0x30, 0x20, 0x00, // k 75

    0x00, 0x08, 0x08, 0xF8, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // l 76

    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00,
    0x20, 0x3F, 0x20, 0x00, 0x3F, 0x20, 0x00, 0x3F, // m 77

    0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00,
    0x20, 0x3F, 0x21, 0x00, 0x00, 0x20, 0x3F, 0x20, // n 78

    0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
    0x00, 0x1F, 0x20, 0x20, 0x20, 0x20, 0x1F, 0x00, // o 79

    0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00,
    0x80, 0xFF, 0xA1, 0x20, 0x20, 0x11, 0x0E, 0x00, // p 80

    0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00,
    0x00, 0x0E, 0x11, 0x20, 0x20, 0xA0, 0xFF, 0x80, // q 81

    0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00,
    0x20, 0x20, 0x3F, 0x21, 0x20, 0x00, 0x01, 0x00, // r 82

    0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00,
    0x00, 0x33, 0x24, 0x24, 0x24, 0x24, 0x19, 0x00, // s 83

    0x00, 0x80, 0x80, 0xE0, 0x80, 0x80, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x00, 0x00, // t 84

    0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00,
    0x00, 0x1F, 0x20, 0x20, 0x20, 0x10, 0x3F, 0x20, // u 85

    0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80,
    0x00, 0x01, 0x0E, 0x30, 0x08, 0x06, 0x01, 0x00, // v 86

    0x80, 0x80, 0x00, 0x80, 0x00, 0x80, 0x80, 0x80,
    0x0F, 0x30, 0x0C, 0x03, 0x0C, 0x30, 0x0F, 0x00, // w 87

    0x00, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00,
    0x00, 0x20, 0x31, 0x2E, 0x0E, 0x31, 0x20, 0x00, // x 88

    0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80,
    0x80, 0x81, 0x8E, 0x70, 0x18, 0x06, 0x01, 0x00, // y 89

    0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00,
    0x00, 0x21, 0x30, 0x2C, 0x22, 0x21, 0x30, 0x00, // z 90

    0x00, 0x00, 0x00, 0x00, 0x80, 0x7C, 0x02, 0x02,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x40, 0x40, //{ 91

    0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, //| 92

    0x00, 0x02, 0x02, 0x7C, 0x80, 0x00, 0x00, 0x00,
    0x00, 0x40, 0x40, 0x3F, 0x00, 0x00, 0x00, 0x00, //} 93

    0x00, 0x06, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //~ 94
};
c

void main()
{
    OLED_Init();
    OLED_Clear();
    OLED_ShowChar(0, 0, 'A');
    OLED_ShowStr(0, 1, "Hello world!");
    OLED_ShowNum(0, 2, -123459, 6);
    while (1);
}
c
//初始化
void Int_OLED_Init()
{
    unsigned char cmd_bytes[6];
    // 关闭屏幕
    cmd_bytes[0] = 0xAE;
    // 行重映射
    cmd_bytes[1] = 0xC8;
    // 列重映射
    cmd_bytes[2] = 0xA1;
    // 电荷泵
    cmd_bytes[3] = 0x8D;
    cmd_bytes[4] = 0x14;
    // 开启屏幕
    cmd_bytes[5] = 0xAF;
    Int_OLED_WriteCmd(cmd_bytes, 6);
}
c
//清零
void Int_OLED_Clear()
{
    unsigned short int i;
    unsigned char data_bytes[8] = {0};
    unsigned char cmd_bytes[2];
    // 设置寻址模式  水平寻址-默认值,省略
    cmd_bytes[0] = 0x20;
    cmd_bytes[1] = 0x00;
    Int_OLED_WriteCmd(cmd_bytes, 2);
    // 直接写入数据
    Dri_IIC_Start();
    Dri_IIC_SendByte(DEV_ADDR);
    Dri_IIC_ReceiveAck();
    Dri_IIC_SendByte(DATA_MODE);
    Dri_IIC_ReceiveAck();
    for (i = 0; i < 128 * 8; i++) {
        Dri_IIC_SendByte(0x00);
        Dri_IIC_ReceiveAck();
    }
    Dri_IIC_Stop();
}
c
//写命令
void Int_OLED_WriteCmd(unsigned char bytes[], unsigned char length)
{
    unsigned char i;
    Dri_IIC_Start();
    Dri_IIC_SendByte(DEV_ADDR);
    Dri_IIC_ReceiveAck();
    Dri_IIC_SendByte(CMD_MODE);
    Dri_IIC_ReceiveAck();
    for (i = 0; i < length; i++) {
        Dri_IIC_SendByte(bytes[i]);
        Dri_IIC_ReceiveAck();
    }
    Dri_IIC_Stop();
}
c
//写数据
void Int_OLED_WriteData(unsigned char bytes[], unsigned char length)
{
    unsigned char i;
    Dri_IIC_Start();
    Dri_IIC_SendByte(DEV_ADDR);
    Dri_IIC_ReceiveAck();
    Dri_IIC_SendByte(DATA_MODE);
    Dri_IIC_ReceiveAck();
    for (i = 0; i < length; i++) {
        Dri_IIC_SendByte(bytes[i]);
        Dri_IIC_ReceiveAck();
    }
    Dri_IIC_Stop();
}
c
// 设置起始位置函数
void Int_OLED_SetPointer(unsigned char page, unsigned char column)
{
    unsigned char cmd_bytes[3];
    // 页地址
    cmd_bytes[0] = 0xB0 | page;
    // 列地址
    cmd_bytes[1] = 0x0F & column;
    cmd_bytes[2] = 0x10 | (column >> 4);
    // 发送指令
    Int_OLED_WriteCmd(cmd_bytes, 3);
}
c
//显示字符
void OLED_ShowChar(unsigned char x, unsigned char y, unsigned char chr)
{
    unsigned char cmd_bytes[2];

    // 设置OLED寻址方式
    cmd_bytes[0] = 0x20; // 设置寻址模式命令
    cmd_bytes[1] = 0x02; // 设置为页寻址模式
    OLED_WriteCmd(cmd_bytes, 2);

    // 显示上半部分
    OLED_SetPointer(2 * y, 8 * x);          // 设置起始位置(页地址、列地址)
    OLED_WriteData(OLED_Font[chr - 32], 8); // 写入上半部分数据

    // 显示下半部分
    OLED_SetPointer(2 * y + 1, 8 * x);          // 设置下半部分起始位置
    OLED_WriteData(OLED_Font[chr - 32] + 8, 8); // 写入下半部分数据
}
c
//显示字符串
void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char *str)
{
    unsigned char i = 0;

    // 遍历字符串,依次显示每个字符
    while (str[i] != '\0') {
        OLED_ShowChar(x, y, str[i]); // 显示字符
        x++;                         // 列位置右移

        // 如果超出一行范围(16列),则退出
        if (x >= 16) {
            break;
        }

        i++; // 处理下一个字符
    }
}
c
//显示数字
unsigned long oled_pow(unsigned char m, unsigned char n)
{
    unsigned long result = 1;
    while (n--) result *= m;
    return result;
}

void OLED_ShowNum(unsigned char x, unsigned char y, long num, unsigned char len)
{
    unsigned char t, i = 0, temp;
    if (num < 0) {
        OLED_ShowChar(x, y, '-');
        num = -num;
        i++;
    }
    for (t = 0; t < len; t++) {
        temp = (num / oled_pow(10, len - t - 1)) % 10;
        OLED_ShowChar(x + t + i, y, temp + '0');
    }
}

显示中文

c
unsigned char code Hzk[][32] = {
    //  你(0) 好(1) ,(2) 世(3) 界(4) !(5)
    {0x00, 0x80, 0x60, 0xF8, 0x07, 0x40, 0x20, 0x18, 0x0F, 0x08, 0xC8, 0x08, 0x08, 0x28, 0x18, 0x00, 0x01, 0x00, 0x00, 0xFF, 0x00, 0x10, 0x0C, 0x03, 0x40, 0x80, 0x7F, 0x00, 0x01, 0x06, 0x18, 0x00}, /*"你",0*/
    {0x10, 0x10, 0xF0, 0x1F, 0x10, 0xF0, 0x00, 0x80, 0x82, 0x82, 0xE2, 0x92, 0x8A, 0x86, 0x80, 0x00, 0x40, 0x22, 0x15, 0x08, 0x16, 0x61, 0x00, 0x00, 0x40, 0x80, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"好",1*/
    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*",",2*/
    {0x20, 0x20, 0x20, 0xFE, 0x20, 0x20, 0xFF, 0x20, 0x20, 0x20, 0xFF, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x40, 0x40, 0x47, 0x44, 0x44, 0x44, 0x47, 0x40, 0x40, 0x40, 0x00, 0x00}, /*"世",3*/
    {0x00, 0x00, 0x00, 0xFE, 0x92, 0x92, 0x92, 0xFE, 0x92, 0x92, 0x92, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x04, 0x84, 0x62, 0x1E, 0x01, 0x00, 0x01, 0xFE, 0x02, 0x04, 0x04, 0x08, 0x08, 0x00}, /*"界",4*/
    {0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"!",5*/
};

void main()
{
    int i;
    OLED_Init();
    OLED_Clear();
    for (i = 0; i < 6; i++) {
        OLED_ShowChinese(i, 0, i, 16); // 第四个参数为字号,需和字模软件中设置的字号一致
    }
    while (1);
}
c
//显示中文
void OLED_ShowChinese(unsigned char x, unsigned char y, unsigned char ch, unsigned char size)
{

    unsigned char cmd_bytes[2];

    // 设置OLED寻址方式
    cmd_bytes[0] = 0x20; // 设置寻址模式命令
    cmd_bytes[1] = 0x02; // 设置为页寻址模式
    OLED_WriteCmd(cmd_bytes, 2);

    // 显示上半部分
    OLED_SetPointer(2 * y, size * x); // 设置起始位置(页地址、列地址)
    OLED_WriteData(Hzk[ch], size);    // 写入上半部分数据

    // // 显示下半部分
    OLED_SetPointer(2 * y + 1, size * x); // 设置下半部分起始位置
    OLED_WriteData(Hzk[ch] + size, size); // 写入下半部分数据
}

显示图片

c
unsigned char code BMP0[] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x60,
    0xE0, 0xE0, 0xE0, 0xE0, 0x60, 0x40, 0x40, 0xC0, 0xC0, 0xC0, 0xC0, 0x80, 0x80, 0x80, 0xC0, 0xE0,
    0x60, 0x20, 0x30, 0x30, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x30, 0x30, 0x30, 0x60, 0x60,
    0xC0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x38, 0x1C, 0x0C, 0x0C, 0x0C, 0x18, 0xB8, 0xF0, 0xC0, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x01, 0x03, 0x03, 0x06, 0x0C, 0x1C, 0x38, 0xF0, 0xF0, 0x60, 0x30, 0x31, 0x39, 0x1F,
    0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x1C, 0x1C, 0x18, 0x00, 0x00, 0x00,
    0x00, 0x01, 0x01, 0x03, 0x0F, 0x3F, 0xF3, 0xC2, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0x63, 0x77, 0x3E, 0x38, 0x38, 0x18, 0x18,
    0x18, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
    0x80, 0x80, 0x80, 0x80, 0xC0, 0xE0, 0x7F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0xC0, 0xF8, 0xFC, 0x0E, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFE, 0x87, 0x03, 0x01, 0x01,
    0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x02, 0x06, 0x0C, 0x18, 0x38, 0x70, 0xE0, 0xC0, 0x80, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x03, 0x1F, 0x7F, 0xF8, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0F, 0x1E, 0x3C, 0x70,
    0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07,
    0x0C, 0x38, 0x70, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0x60, 0xE0, 0xC0, 0xC0, 0x80,
    0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x01, 0x03, 0x03, 0x06, 0x0C, 0x18, 0x38, 0x70, 0xE0, 0xC0, 0x80, 0x80, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x1E, 0x38, 0xF0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x06, 0x06, 0x06, 0x06,
    0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0E,
    0x0E, 0x0E, 0x0E, 0x0C, 0x0E, 0x0E, 0x0C, 0x0C, 0x04, 0x04, 0x04, 0x04, 0x0E, 0x0E, 0x0F, 0x0F,
    0x7F, 0x3F, 0x1F, 0x0F, 0x0E, 0x0E, 0x0E, 0x0C, 0x0C, 0x0C, 0x8C, 0xEC, 0xFC, 0x3C, 0x1C, 0x0C,
    0x1C, 0x7E, 0x7E, 0x0E, 0x1E, 0x1E, 0x3E, 0x7E, 0x6C, 0x0C, 0x0C, 0x09, 0x0B, 0x0F, 0x0E, 0x0E,
    0x0C, 0x18, 0x18, 0x30, 0x30, 0x30, 0x60, 0xE0, 0xE0, 0xE3, 0xFF, 0xBE, 0x8E, 0x8C, 0x8C, 0x8C,
    0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x84, 0x84, 0x84, 0x84,
    0x84, 0x86, 0x86, 0x86, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06,
    0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x02,
    0x02, 0x06, 0x06, 0x06, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
    0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x33, 0x3F, 0x0F, 0x03, 0x03, 0x03, 0x03, 0x03,
    0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
    0x0F, 0x1F, 0x39, 0x21, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
    0x01, 0x01, 0x01, 0x01, 0x03, 0x07, 0x07, 0x0D, 0x19, 0x31, 0x21, 0x01, 0x01, 0x01, 0x01, 0x01,
    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

void main()
{
    int i;
    OLED_Init();
    OLED_Clear();
    OLED_ShowImage(0, 0, 128, 64, BMP0); // 字模软件中导入的图片的宽高要和第三个、第四个参数一样
    while (1);
}
c
//显示图片
void OLED_ShowImage(unsigned char x, unsigned char y, unsigned char sizex, unsigned char sizey, unsigned char BMP[])
{
    unsigned short j = 0;
    unsigned char i, m;

    unsigned char cmd_bytes[2];

    // 设置OLED寻址方式
    cmd_bytes[0] = 0x20; // 设置寻址模式命令
    cmd_bytes[1] = 0x02; // 设置为页寻址模式
    OLED_WriteCmd(cmd_bytes, 2);

    sizey = sizey / 8 + ((sizey % 8) ? 1 : 0);
    for (i = 0; i < sizey; i++) {
        OLED_SetPointer(i, x);
        for (m = 0; m < sizex; m++) {
            OLED_WriteData(&BMP[j++], 1);
        }
    }
}

DS1302 时钟

其中涉及到的一些知识点
符号描述说明具体描述
VCC2主电源接电源正极
VCC1后备电源接电源正极
X1/X2振荡源外接 32.768KHz 晶振
CE/RST复位输入信号,在读、写数据期间,必须为高
I/O数据输入/输出见下方 寄存器地址
SCLK串行时钟输入

寄存器地址

LCD1602 显示实时时间

下方代码是在 LCD1602 基础上添加了 DS1302 时钟实时显示,其余代码在 LCD1602 基础上没有改动。 里面的 LCD_ShowString、LCD_ShowString 可以看上面的扩展方法

c
sbit RST  = P3 ^ 0;
sbit SCLK = P3 ^ 1;
sbit IO   = P3 ^ 2;

unsigned char DS1302_Time[] = {30, 31, 18, 4, 12, 24, 3}; // 秒分时日月年星期几

void main()
{
    LCD_Init(); // LCD1602 初始化
    LCD_ShowString(1, 1, "  -  -  ");
    LCD_ShowString(2, 1, "  :  :  ");
    while (1) {
        read_time();
        LCD_ShowNum(1, 1, DS1302_Time[5], 2); // 显示年
        LCD_ShowNum(1, 4, DS1302_Time[4], 2); // 显示月
        LCD_ShowNum(1, 7, DS1302_Time[3], 2); // 显示日
        LCD_ShowNum(2, 1, DS1302_Time[2], 2); // 显示时
        LCD_ShowNum(2, 4, DS1302_Time[1], 2); // 显示分
        LCD_ShowNum(2, 7, DS1302_Time[0], 2); // 显示秒
    }
}
c
//写数据
void write_ds1302(unsigned char add, unsigned char dat)
{

    unsigned char i;
    RST = 1;                  // 把复位线拿高
    for (i = 0; i < 8; i++) { // 低位在前
        SCLK = 0;             // 时钟线拿低开始写数据
        IO   = add & 0x01;
        add >>= 1; // 把地址右移一位
        SCLK = 1;  // 时钟线拿高
    }
    for (i = 0; i < 8; i++) {
        SCLK = 0; // 时钟线拿低开始写数据
        IO   = dat & 0x01;
        dat >>= 1; // 把数据右移一位
        SCLK = 1;  // 时钟线拿高
    }
    RST  = 0; // 复位线合低
    SCLK = 0;
    IO   = 0;
}
c
//读数据
unsigned char read_ds1302(unsigned char add)
{
    unsigned char value, i;
    RST = 1;                  // 把复位线拿高
    for (i = 0; i < 8; i++) { // 低位在前
        SCLK = 0;             // 时钟线拿低开始写数据
        IO   = add & 0x01;
        add >>= 1; // 把地址右移一位
        SCLK = 1;  // 时钟线拿高
    }
    for (i = 0; i < 8; i++) {
        SCLK = 0; // 时钟线拿低开始读数据
        value >>= 1;
        if (IO == 1)
            value |= 0x80;
        SCLK = 1; // 时钟线拿高
    }
    RST  = 0; // 复位线合低
    SCLK = 0;
    IO   = 0;
    return value; // 返回读出来的数据
}
c
// BCD码转换为数字
// 返回值为十进制数字
unsigned char datadeal(unsigned char num)
{
    return ((num / 16)) * 10 + num % 16;
}
// 数字转换为BCD码
// 返回值为BCD码
unsigned char to_BCD(unsigned char num)
{
    return (((num / 10) << 4) | (num % 10));
}
c
unsigned char code write_add[] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8c, 0x8a}; // 写地址
unsigned char code read_add[]  = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8d, 0x8b}; // 读地址

// 读取时间
void read_time()
{
    DS1302_Time[0] = datadeal(read_ds1302(read_add[0])); // 读秒
    DS1302_Time[1] = datadeal(read_ds1302(read_add[1])); // 读分
    DS1302_Time[2] = datadeal(read_ds1302(read_add[2])); // 读时
    DS1302_Time[3] = datadeal(read_ds1302(read_add[3])); // 读日
    DS1302_Time[4] = datadeal(read_ds1302(read_add[4])); // 读月
    DS1302_Time[5] = datadeal(read_ds1302(read_add[5])); // 读年
    DS1302_Time[6] = datadeal(read_ds1302(read_add[6])); // 读星期
}

//写入时间
void write_time()
{
    write_ds1302(0x8e, 0x00);                           // 打开写保护
    write_ds1302(write_add[0], to_BCD(DS1302_Time[0])); // 写秒
    write_ds1302(write_add[1], to_BCD(DS1302_Time[1])); // 写分
    write_ds1302(write_add[2], to_BCD(DS1302_Time[2])); // 写时
    write_ds1302(write_add[3], to_BCD(DS1302_Time[3])); // 写日
    write_ds1302(write_add[4], to_BCD(DS1302_Time[4])); // 写月
    write_ds1302(write_add[5], to_BCD(DS1302_Time[5])); // 写年
    write_ds1302(write_add[6], to_BCD(DS1302_Time[6])); // 写星期
    write_ds1302(0x8e, 0x80);                           // 关闭写保护
}

数码管 显示实时时间

c
int seg[10] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90};

void main()
{
    int i;
    while (1) {
        read_time();
        for (i = 0; i < 8; i++) {
            P2 = 1 << i;
            if (i == 0) {
                P0 = seg[DS1302_Time[2] / 10];
            } else if (i == 1) {
                P0 = seg[DS1302_Time[2] % 10];
            } else if (i == 3) {
                P0 = seg[DS1302_Time[1] / 10];
            } else if (i == 4) {
                P0 = seg[DS1302_Time[1] % 10];
            } else if (i == 6) {
                P0 = seg[DS1302_Time[0] / 10];
            } else if (i == 7) {
                P0 = seg[DS1302_Time[0] % 10];
            } else {
                P0 = 0xbf;
            }
            delay(500);
            P0 = 0xff; // 消除拖影
        }
    }
}

OLED 显示实时时间

下方代码是在 OLED 显示屏 基础上添加了 DS1302 时钟实时显示,其余代码在 OLED 显示屏 基础上没有改动。 OLED_ShowNumOLED_ShowChinese 方法的实现

c
unsigned char code date[][32] = {
    {0x00, 0x20, 0x18, 0xC7, 0x44, 0x44, 0x44, 0x44, 0xFC, 0x44, 0x44, 0x44, 0x44, 0x04, 0x00, 0x00, 0x04, 0x04, 0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0xFF, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00}, /*"年",0*/
    {0x00, 0x00, 0x00, 0xFE, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xFE, 0x00, 0x00, 0x00, 0x80, 0x40, 0x30, 0x0F, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x42, 0x82, 0x7F, 0x00, 0x00, 0x00}, /*"月",1*/
    {0x00, 0x00, 0x00, 0xFE, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xFF, 0x00, 0x00, 0x00, 0x00}, /*"日",2*/
};

void main()
{
    OLED_Init();
    OLED_Clear();

    OLED_ShowChinese(1, 0, 0, 16); // 年
    OLED_ShowChinese(3, 0, 1, 16); // 月
    OLED_ShowChinese(5, 0, 2, 16); // 日
    OLED_ShowChar(2, 1, ':');
    OLED_ShowChar(5, 1, ':');

    while (1) {
        read_time();
        OLED_ShowNum(0, 0, DS1302_Time[5], 2); // 年
        OLED_ShowNum(4, 0, DS1302_Time[4], 2); // 月
        OLED_ShowNum(8, 0, DS1302_Time[3], 2); // 日

        OLED_ShowNum(0, 1, DS1302_Time[2], 2); // 时
        OLED_ShowNum(3, 1, DS1302_Time[1], 2); // 分
        OLED_ShowNum(6, 1, DS1302_Time[0], 2); // 秒
    }
}

PWM 波

具体效果可以查看下方的 SG90 舵机 部分。

SG90 舵机

其中涉及到的一些知识点
符号描述说明具体描述
PWM信号线橙线
GND电源地棕线
VCC电源正极红线

SG90 舵机 采用 PWM 波 进行驱动,其余代码去 PWM 波 模块寻找

注意

有些舵机只能 正转,有些只能 反转,有些 正反转 都可以,不要用错了。舵机的需要的电压范围是 4.8V ~ 6V,所以遇到舵机不转或者卡主 的情况可能电压不够,需要额外供电,连接一个电池即可。

直流电机

HC05 蓝牙模块

其中涉及到的一些知识点
  • Protues 没有蓝牙模块,我们从外部导入下载地址,将下载的两个文件放入下面的目录
符号描述说明具体描述
RXD接收数据
TXD发送数据
VCC电源正极
GND电源地

点灯

其余代码和上方的串口通信一样

c
void main()
{
    UsartInit();
    while (1) {
        if (UartBuf) {
            P0 = UartBuf;
        }
    }
}

连接如下图所示

APP 点灯

等我后面弄个 Android 机再来写

总结

贡献者

暂无相关贡献者

变更记录

暂无最近变更历史

Released under the MIT License.