文章地址:https://www.cnblogs.com/jqdy/p/12665430.html

1. 硬件连接

1.1 64引脚的STC8A8K64S4A12

  使用的是最小核心板,所以引脚皆引出可供使用。其他接口只有USB口,起到供电及下载烧写的作用。

1.2 12864液晶模块

  店家提供的使用说明较为杂乱,后续除模块信息外,关于控制芯片的内容均参考ST7920手册。

  • 显示控制芯片使用的是ST7920
  • 模块有20个外接引脚(见图2)
  • PCB背板有选择串口和并口的两组焊点,短接后可分别选择串口和并口
  • 背板有一个可调电阻,用以调节对比度

1.3 连接方式

  因为还有其他几个外接模块,显示模块采用并口会占用过多I/O口,所以采用SPI串口连接方式,连接示意图及照片图1、图2所示。

图1:连接示意图

图2:照片示意图

  其中有几点需要特别说明:

1.3.1 模块的RST复位引脚是否需要连接

  模块手册上明确说明上电后模块自动复位,开始将RST连接到GND没有发现问题,但在调试过程中发现,如果上一次程序跑飞,液晶模块显示满屏“雪花”(注意不是乱码),下次烧写后无论程序对错,屏幕基本上保持原样,会影响到思路判断,还以为是程序仍然没有调试正确。估计其原因是ST7920被跑飞的程序置于某种状态,不再接收正确的指令了。

  因此,在调试过程中还是要连上此脚加上复位功能。即便是正式发布的程序,在系统无断电机会时,为了避免潜在Bug的影响,还是加上复位控制为好。

  ST7920手册记载,RST为低电平复位,保持时间在10us以上。

1.3.2 ST7920片选引脚是否连接

  如果只有一个外设使用SPI总线,可以不用将CS连接到单片机,直接将CS连接到Vcc即可,CS高电平有效。SPI总线上的设备超过一个时,就需要单片机控制CS信号了。

1.3.3 单片机SPI接口的SS脚如何处理

  SPI控制寄存器SPCTL的B7位SSIG明确了SS的功能。SSIG英文全称应该是Selected Slave Ignore(杜撰),字面意思是“忽略被选为从机的信号”,即STC8是否允许其他设备通过拉低SS脚电平把自己作为从机,SSIG=0代表允许,SSIG=1代表不允许。因此,在STC8总是作为主机的情况下,可以不用连接SS脚,软件配置上有两种选择

  • SSIG=1,忽略SS脚信号的控制作用。这种情况下,SS脚是否能做他用有待验证。
  • SSIG=0,配合SPCTL的B4位MSTR=1来保持主机地位。

  ST7920就是被动接收信息,不会作为主机控制SPI总线,模块也没有提供响应的引脚,因此就ST7920而言不用连接SS脚。但是我计划SPI总线上还有其他设备有可能以主机身份存在,因此SS脚暂时悬空,程序中仍然配置SSIG=0。

1.3.4 电源电压问题

  模块手册明确使用电压3.3-5.3V,实际接到5V电源时背光明亮,3V时柔和舒适,除此之外还需要调整一下PCB背板上的对比度可调电阻,否则字迹显示不清楚。

2. STC8A8K64S4A12SPI接口配置及操作

  该芯片使用SPI接口需要4个步骤,之后就可传输数据了。可根据实际情况省略前两个步骤:

  • 选择I/O口
  • 选择I/O口工作模式
  • 配置SPI控制寄存器
  • 中断使能

2.1 接口配置

2.1.1 选择I/O

  该芯片可将SPI功能脚配置到四组不同的I/O口,可以根据需要进行选择,外设端口切换寄存器1“P_SW1”的B3和B2位SPI_S[1:0] (SPI_Select)就起到这个作用,详情见表1和表2。

  因为P7口的复用功能比较少,我先将SPI配置到P7上,即SPI_S=10。这两位的上电复位默认值为“00”,若忽略选择I/O口这一步,SPI的I/O口将被定位在P1的4个口上。

表1:SPI端口切换寄存器(表中第二个)

表2 SPI功能脚选择位

2.1.2 选择I/O口工作模式

  该芯片所有I/O口都有四种工作模式:准双向口、推挽输出、高阻输入和开漏输出,可根据需要进行选择。需要配置寄存器是P0M1、P0M0 – P7M1、P7M0,共8对分别对应P0~P7。这些端口上电复位值均为0,如果忽略该步骤,所有I/O口均工作在准双向模式。我的方案就是省略该步骤采用默认值,也就是说SPI的四个口都工作在准双向模式。

  P0~P7(P4没有4.5~4.7口)每个端口都有两个端口模式寄存器,例如:P0口的B7~B0位对应的两个模式寄存器是P0M1和P0M0的B7~B0位,这一对寄存器用来确定对应的I/O口工作在四种模式中的哪一种。PnM1.x和 PnM0.x(n=1~7)分别为:

  • 00:准双向口:灌电流20mA,拉电流270~150uA。可见准双向口提供的驱动能力是有较大差异的,某个口为0时可容纳20mA电流流入,为1时输出电流要小约100倍(74-133倍)
  • 01:推挽输出:向上拉输出,可达20mA,要加限流电阻
  • 10:高阻输入:电流既不能流入,也不能流出,需要配合外部电路实现0、1的功能
  • 11:开漏输出:外加上拉电阻时,即可输入也可输出,否则读不到外部状态,也对外输不出高电平

2.1.3 配置SPI控制寄存器SPCTLSPI Control Register

  该寄存器的配置是操作SPI总线的重头戏,该寄存器的结构如表3所示。因为不用考虑兼容8051,SPI的所有控制位都集中到这个寄存器中。

表3 SPI三个寄存器的结构

  SPCTL共8个位,可以实现SPI总线7个方面的功能控制,为便于理解,下面尽可能用通俗的语言进行描述。

2.1.3.1 [B7]SSIGSelected Slave Ignore

  英文直译的意思是“忽略从设备选择信号”,芯片手册上称之为“SS引脚功能控制位”,但这个叫法不太容易理解,实际上就如本文1.1.3所言,其功能就是“是否允许其他设备通过拉低SS脚电平把自己作为从机”。

  SSIG的两种状态通俗的讲,就是话语权的问题,理解了这一点对“单主单从”、“互为主从”、“一主多从”的设置很关键:

  • 0:允许其他设备占主动权,若想将本机作为从机,其他设备将本机SS脚电平拉低就可实现这个目的。
  • 1:我永远占主动权,是主是从你们说了不算,我说了才算。让你们是从机的时候,你们就是从机,这时B4位MSTR=1,即表示我是主机,你们是从机;让你们是主机的时候,你们才能是主机,这时B4位MSTR=0,表示我是从机。

2.1.3.2 [B6]SPENSPI Enable

  SPI使能控制位,0=关闭SPI功能,1=使能。

2.1.3.3 [B5]DORDData Order

  数据位收发时的顺序,0=先高位MSB,1=先低位(LSB)。ST7920要求先高后低,因此该位应该设为0。

2.1.3.4 MSTRMaster

  MSTR:器件主/从模式选择位,SSIG章节已经掰嗤清楚了,这里不说了,抄手册。

  设置主机模式:

  • 若 SSIG=0,则 SS 管脚必须为高电平且设置 MSTR 为 1
  • 若 SSIG=1,则只需要设置 MSTR 为 1(忽略 SS 管脚的电平)

  设置从机模式:

  • 若 SSIG=0,则 SS 管脚必须为低电平(与 MSTR 位无关)
  • 若 SSIG=1,则只需要设置 MSTR 为 0(忽略 SS 管脚的电平)

2.1.3.5 [B3] CPOLClock PolaritySPI时钟极性控制)与[B2] CPHAClock PhaseSPI时钟相位控制)

  CPOL:SPI 时钟极性控制。

  • 0:SCLK 空闲时为低电平,SCLK 的前时钟沿为上升沿,后时钟沿为下降沿
  • 1:SCLK 空闲时为高电平,SCLK 的前时钟沿为下降沿,后时钟沿为上升沿

  CPHA:SPI 时钟相位控制

  • 0:数据 SS 管脚为低电平驱动第一位数据并在 SCLK 的后时钟沿改变数据,前时钟沿采样数据(必 须 SSIG=0)
  • 1:数据在 SCLK 的前时钟沿驱动,后时钟沿采样

  手册中给出的描述很简单,但是理解起来很是困难,有一篇帖子说的再明白不过了,摘抄了一张图稍作修改(图3),原文链接:高手带你理解SPI中的极性CPOL和相位CPHA

图3:SPI时钟极性与相位示意图

  我在这里遇到理解障碍主要有两点,对于判断这两位的高低十分重要。

  1. 手册中说的SCLK空闲时间指的是什么时间?

  答:指的是SPI总线启动前的时间。以ST7920为例,其时序图如图4所示,图中的时间是我根据手册数据加上去的。传输数据之前SCLK处于高电平状态,即极性CPOL=1。可恨的是手册写的水平不高,也可能是我理解能力有限,手册还给出了一张图(图5),正好拧着,好坑人。

图4:ST7920串口时序图

图5:坑人的另一张图

  2.       哪里算作SCLK的开始时间?

  明确开始时间,才能搞清楚哪里是第一个时钟沿,哪里是第二个时钟沿。搞清楚第一个问题后,这个问题就十分容易了。不难看出ST7920要求相位CPHA = 1。

2.1.3.6 SPR[1:0]

  英文应该是SPI Rate,即SPI时钟的波特率,占B1和B0两个位。手册给出的数值为:

  • 00:SYSclk÷4
  • 01:SYSclk÷8
  • 10:SYSclk÷16
  • 11:SYSclk÷32

  由此可见,在该单片机系统时钟固定的情况下,SPI时钟的波特率只有4种选择,分别是系统时钟的4、8、16、32分频。如果想使用其他频率,就必须调整系统时钟频率了。

  我选择的系统时钟频率是22.1184MHz,应该选择哪个分频还需要看ST7920的要求,ST7920在两种电压下对时钟周期的要求是不同的,见表4和表5。可见在工作电压越低,ST7920的工作速度越慢,在2.7V条件下的时钟周期Tscyc最小为600ns,在4.5V时最小为400ns。STC8A8K64S4A12的工作电压我选择的是3V,因此按照2.7V的600ns来计算肯定可以满足ST7920的要求。

1秒÷600纳秒=1.67MHz,这是ST7920要求的频率上限。

  有了这个数就好办了,一一计算22.1184MHz的四种分频,不难得出选择16分频为佳,22.1184 MHz÷16 = 1.3824MHz。因此SPR[1:0]的这两位选择10。

表4:ST7920在4.5V条件下的时间要求

表5:ST7920在2.7V条件下的时间要求

2.2 SPI中断的使能操作

  使能操作要简单的多,SPI的使能位在IE2的B1位------ESPI,见表6。先将ESPI=1,再打开总中断EA=1,就完成了SPI的使能操作。

表6:中断使能寄存器 IE2

2.3 SPI传输数据操作

  使用SPI传输数据涉及两个寄存器,就是表1中的状态寄存器SPSTAT(SPI Status Register)和数据寄存器SPDAT(SPI Data Register)。

  这里只有两点需要说明:

  1.       按说可以利用SPI中断自动实现SPI的数据传输,可我反复尝试最终失败了,还是选择了常规的发送数据后,等待中断产生,手工清除状态寄存器的方式。有可能是STC8手册《A.2 关于使用CLR指令关闭EA的重要说明》提到“使用4级流水线”的原因。

  2.       状态寄存器标识位的清零需要写1(SPSTAT = 0xc0),不能使用常规的清零方法(SPSTAT = 0)。

3. ST7920的操作

  SPI串口设置好了,就可以根据ST7920手册要求顺利操作了,网上的例子也多。

  这里需要说明的是:

  1、 选择串口方式,需要将背板上的“S”点,用焊锡短接,见图6。这一点根据模块不同可能有不同的方式。

图6 模块PCB背板局部

  2 、网上的例子中每次操作ST7920配的延时时间各不相同,我尝试了一下,各种操作只要保证手册要求的72us即可(清屏操作需等待1.6ms)。这有可能与采用的显示控制芯片有关。

  3 、串口方式向ST7920发送命令或数据的步骤

  发送每个命令或数据都要发送三个字节的信息:

  • 第一个字节:启动字节。若后面跟的是命令,启动字节=0xf8;后面跟的是数据启动字节=0xfa。
  • 第二、三个字节:要发送的命令或数据。原本命令或数据都是一个字节8位的,发送时需要拆成两次发送,第二个字节的高4位是命令或数据字节的高4位,第三个字节的高4位是命令或数据字节的低4位,空出来的位均为0。

  4 、关于DDRAM地址与屏幕坐标的关系

  这一点手册中说的也不太清楚,用表格表示一下,见表7。表中的数字均为16进制,例如80表示0x80;每个地址应该是个16位数,以0x80为例说明,高8位表中用80.H表示,低8位表中用80.L表示。

表7 屏幕坐标和DDRAM地址的对应关系

4 主要程序

  因为我使用Visual Studio 2019作为编辑器,所以使用了更多的VS习惯,以便更多的利用VS的自动提示功能。如何在VS中编辑,在Keil中调试请见:如何发挥Visual Studio 2019强大的编辑功能轻松编辑Keil项目

 //SPI配置
#include <STC8.H>
#include "System.h" //主要定义了unsigned char为u8等等 /// <summary>
/// SPI单主多从模式的主机初始化
/// </summary>
/// <param name="dataOrder">传输字节哪头优先</param>
/// <param name="clockPolarity">时钟极性控制</param>
/// <param name="clockPhase">时钟相位控制</param>
/// <param name="spiSpeed">时钟频率</param>
/// <param name="pinSelect">功能脚组别选择</param>
/// <returns></returns>
void STC8_SPI_One_Master_Many_Slave_Init(u8 dataOrder, u8 clockPolarity, u8 clockPhase, u8 spiSpeed, u8 pinSelect )
{
// 第一步:选择输出脚
P_SW1 &= 0xf3; // P_SW1同时还负责着串口1、CCP的管脚选择,注意不能覆盖
P_SW1 |= pinSelect;
//第二步:配置IO脚工作模式为准双向口/弱上拉,即处于00
//第三步:控制寄存器配置
SPCTL = 0x50;
SPCTL |= (dataOrder | clockPolarity | clockPhase | spiSpeed);
SPSTAT = 0xc0; //写1清零
IE2 |= ESPI; //使能SPI中断
EA = ;
}

  上边程序片段用的到几个宏在包含文件中:

#include "System.h"
#define STC8_SPI_PIN_P12_P13_P14_P15 0x00 // SPI输出脚按顺序分别是SS/MOSI/MISO/SCLK
#define STC8_SPI_PIN_P22_P23_P24_P25 0x04 // SPI输出脚按顺序分别是SS/MOSI/MISO/SCLK
#define STC8_SPI_PIN_P74_P75_P76_P77 0x08 // SPI输出脚按顺序分别是SS/MOSI/MISO/SCLK
#define STC8_SPI_PIN_P35_P34_P33_P32 0x0c // SPI输出脚按顺序分别是SS/MOSI/MISO/SCLK #define STC8_SPI_DATA_ORDER_MSB_FIRST 0x00 // SPI传送字节高位在先,0000 0000
#define STC8_SPI_DATA_ORDER_LSB_FIRST 0x20 // SPI传送字节低位在先,0010 0000
#define STC8_SPI_POLARITY_IDLE_LOW 0x00 // SPI时钟空闲时低电平,0000 0000
#define STC8_SPI_POLARITY_IDLE_HIGH 0x08 // SPI时钟空闲时高电平,0000 1000
#define STC8_SPI_PHASE_SAMPLING_FIRST_EDGE 0x00 // 在第一个时钟沿采样 ,0000 0000
#define STC8_SPI_PHASE_SAMPLING_SECOND_EDGE 0x04 // 在第二个时钟沿采样,0000 0100
#define STC8_SPI_SPEED_SYSCLOCK_DIVIDE_4 0x00 // SCLK频率为SYSclk 4分频,0000 0000
#define STC8_SPI_SPEED_SYSCLOCK_DIVIDE_8 0x01 // SCLK频率为SYSclk 8分频,0000 0001
#define STC8_SPI_SPEED_SYSCLOCK_DIVIDE_16 0x02 // SCLK频率为SYSclk 16分频,0000 0010
#define STC8_SPI_SPEED_SYSCLOCK_DIVIDE_32 0x03 // SCLK频率为SYSclk 32分频,0000 0011 /// <summary>
/// SPI单主多从模式的主机初始化
/// </summary>
/// <param name="dataOrder">传输字节哪头优先</param>
/// <param name="clockPolarity">时钟极性控制</param>
/// <param name="clockPhase">时钟相位控制</param>
/// <param name="spiSpeed">时钟频率</param>
/// <param name="pinSelect">功能脚组别选择</param>
/// <returns></returns>
void STC8_SPI_One_Master_Many_Slave_Init(u8 dataOrder, u8 clockPolarity, u8 clockPhase, u8 spiSpeed, u8 pinSelect);

  ST7920的主要部分:

 #include <STC8.H>
#include "System.h"
#include "Common.h" //主要定义了延时函数 #define COMMAND_CODE 0xf8 // 命令首字节
#define DATA_CODE 0xfa //数据首字节 #define CSEN 1 //ST7920片选有效为高电平
#define CSDS 0 #define DELAY_TIME 72 // 除Clear外所有命令都需要72us延时,专门定义宏,需要时好调整 sbit rst = P7 ^ ; //12864复位信号,复位低电平有效,持续时间10us
sbit cs = P7 ^ ; //12864片选定义在P7.3 /// <summary>
/// ST7920硬复位
/// </summary>
/// <returns></returns>
void ST7920_Reset()
{
rst = ;
DelayUs_1T_221184();
rst = ;
DelayMs_1T_221184(); //复位40毫秒后系统可用
} void wrt_byte(u8 byte)
{
cs = CSEN;
IE2 &= 0xfd; //关SPI中断
SPDAT = byte;
while (!(SPSTAT & 0x80));
SPSTAT = 0xc0; //写1清零
IE2 |= ESPI; //STC8.H定义ESPI = 0x02
cs = CSDS;
} /// <summary>
/// 向ST7920发送命令字节
/// </summary>
/// <param name="cmd">命令字节</param>
/// <returns></returns>
void ST7920_SendCommand(u8 cmd)
{
wrt_byte(COMMAND_CODE);//命令首字节
wrt_byte(cmd & 0xf0);//命令字节高4位
wrt_byte(cmd << ); //命令字节低4位
DelayUs_1T_221184(DELAY_TIME);//7920要求72us
} /// <summary>
/// 向ST7920发送数据字节
/// </summary>
/// <param name="cmd">数据字节</param>
/// <returns></returns>
void ST7920_SendData(u8 data_)
{
wrt_byte(DATA_CODE);//数据首字节
wrt_byte(data_ & 0xf0); //数据字节高4位
wrt_byte(data_ << ); //数据字节低4位
DelayUs_1T_221184(DELAY_TIME);//7920要求72us
} /// <summary>
/// 功能同ST7920_SetDDRAMAddrss(),只是把类似于0x80的地址转变成行和列,基本指令集
/// </summary>
/// <param name="row">行数(0-3)</param>
/// <param name="col">列数(0-15)</param>
/// <returns></returns>
void ST7920_SetDisplayPosition(u8 row, u8 col)
{
u8 address;
if (row == 0x00) address = 0x80;
if (row == 0x01) address = 0x90;
if (row == 0x02) address = 0x88;
if (row == 0x03) address = 0x98;
address += col;
ST7920_SendCommand(address);
} /// <summary>
/// 写16×16点阵全宽字形(CGRAM:0000H、0002H、0004H、0006H;CGROM:A1A0H-F7FFH(GB)或A140H-D75FH(BIG5) )
/// </summary>
/// <param name="hByte">高8位字形编码</param>
/// <param name="lByte">低8位字形编码</param>
/// <returns></returns>
void ST7920_DisplayChar_16_16(u8 hByte, u8 lByte)
{
ST7920_SendData(hByte);
ST7920_SendData(lByte);
} void ST7920_DisplayString_16_16(u8 * str, u8 lenth)
{
u8 i = ;
for (; i < lenth; i += )
{
ST7920_SendData(str[i]);
ST7920_SendData(str[i + ]);
}
}

  上面代码用的的包含文件:

 #include "System.h"
#include "Common.h" /// <summary>
/// ST7920硬复位
/// </summary>
/// <returns></returns>
void ST7920_Reset(); /// <summary>
/// 发送命令
/// </summary>
/// <param name="data_">要发送的命令</param>
/// <returns></returns>
void ST7920_SendCommand(u8 cmd); /// <summary>
/// 发送数据到内部 RAM ( DDRAM/CGRAM/IRAM/GRAM)
/// </summary>
/// <param name="data_">要发送的数据</param>
/// <returns></returns>
void ST7920_SendData(u8 data_); //基本指令集
#define ST7920_Clear() do{ST7920_SendCommand(0x01);DelayMs_1T_221184(2);}while(0) // 清屏,7920要求延时1.6ms(基本指令集)
#define ST7920_HOME 0x02 // 地址归位,基本指令集,DDRAM的地址计数器AC到00H
#define ST7920_DISPLAY_NORMAL 0x0c // 整体显示开,游标关,反白关(基本指令集),总功能:0000 1D(1/0,总体显示开/关)C(1/0,游标开/关)B(1/0,游标位置反白开/关)
#define ST7920_ENTRY_NORMAL 0x06 // 游标及显示右移一次(基本指令集)
#define ST7920_XX 0x10 // 不理解,待后续试验观察
#define ST7920_BASIC_INSTRUCTION 0x30 // 选择8位数据接口的基本指令集
#define ST7920_EXTENDED_INSTRUCTION 0x34 // 选择8位数据接口的扩展指令集
#define ST7920_SetCGRAMAddress(address) do{ST7920_SendCommand(0x40+address);}while(0) //设定CGRAM地址
#define ST7920_SetDDRAMAddress(address) do{ST7920_SendCommand(address);}while(0) //将显存DDRAM地址设置到地址计数器AC,基本指令集。范围:第1行:80H-8FH,第2行:90H-9FH,第3行:A0H-AFH,第4行:B0H-BFH
#define ST7920_DisplayChar_16_8(char_) do{ST7920_SendData(char_);}while(0) //写16×8半宽字形(HCGROM:02H-7FH) /// <summary>
/// 功能同ST7920_Set_DDRAM_Addrss(),只是把类似于0x80的地址转变成行和列,基本指令集
/// </summary>
/// <param name="row">行数(0-3)</param>
/// <param name="col">列数(0-15)</param>
/// <returns></returns>
void ST7920_SetDisplayPosition(u8 row, u8 col); /// <summary>
/// 写16×16点阵全宽字形(CGRAM:0000H、0002H、0004H、0006H;CGROM:A1A0H-F7FFH(GB)或A140H-D75FH(BIG5) )
/// </summary>
/// <param name="hByte">高8位字形编码</param>
/// <param name="lByte">低8位字形编码</param>
/// <returns></returns>
void ST7920_DisplayChar_16_16(u8 hByte, u8 lByte); /// <summary>
/// 写16×16点阵全宽字形字符串(CGRAM:0000H、0002H、0004H、0006H;CGROM:A1A0H-F7FFH(GB)或A140H-D75FH(BIG5) )
/// </summary>
/// <param name="str">字符串指针</param>
/// <param name="lenth">字符串长度(一个全宽字形长度为2)</param>
/// <returns></returns>
void ST7920_DisplayString_16_16(u8 *str, u8 lenth);

  主程序:

 #include "system.h"
#include "STC8_SPI.h"
#include "st7920.h"
#include "Common.h" /// <summary>
/// ST7920初始化
/// </summary>
/// <returns></returns>
void ST7920_Init()
{
DelayMs_1T_221184();//该显示模块要求上电后延迟40ms
ST7920_SendCommand(ST7920_BASIC_INSTRUCTION); //基本指令集
ST7920_SendCommand(ST7920_DISPLAY_NORMAL);//显示开,游标关,反白关
ST7920_Clear(); // 用空格清屏
ST7920_SendCommand(ST7920_ENTRY_NORMAL); // 读写后游标及显示右移
} unsigned char str[] = "配置接口"; void main()
{
STC8_SPI_One_Master_Many_Slave_Init( //配置ST7920SPI接口
STC8_SPI_DATA_ORDER_MSB_FIRST,
STC8_SPI_POLARITY_IDLE_HIGH,
STC8_SPI_PHASE_SAMPLING_SECOND_EDGE,
STC8_SPI_SPEED_SYSCLOCK_DIVIDE_16,
STC8_SPI_PIN_P74_P75_P76_P77);
ST7920_Init();
ST7920_SetDisplayPosition(, );
ST7920_DisplayString_16_16("要以热爱祖国为荣", );
ST7920_SetDisplayPosition(, );
ST7920_DisplayString_16_16("祖国就是我们母亲", );
ST7920_SetDisplayPosition(, );
ST7920_DisplayString_16_16("无私奉献报效祖国", );
ST7920_SetDisplayPosition(, );
ST7920_DisplayString_16_16("这是每个公民责任", );
while ();
}
//SPI中断
void SPI_Interrup() interrupt
{
SPSTAT = 0xc0; //写1清零
}

5 显示效果

STC8A8K64S4A12通过SPI接口操作基于ST7920的LCD12864液晶模块的更多相关文章

  1. EEPROM的操作---SPI接口和I2C接口

    参考:http://blog.csdn.net/yuanlulu/article/details/6163106 ROM最初不能编程,出厂什么内容就永远什么内容,不灵活.后来出现了PROM,可以自己写 ...

  2. CC3000 SPI接口编程介绍

    CC3000 SPI 操作: CC3000的SPI 是基于五根线CLCK,CSn,IRQ,MISO,MOSI:通信模式如下图: CLCK:时钟频率0-26M从主机到从机,提供SPI接口时钟 CSn:低 ...

  3. SPI接口扫盲 SPI定义/SPI时序(CPHA CPOL)

    SPI接口扫盲   douqingl@gmail.com   为何要写这篇文档?百度上找出来的SPI接口中文描述都说的太过简略,没有一篇文档能够详尽的将SPI介绍清楚的.wikipedia英文版[注释 ...

  4. linux驱动基础系列--Linux下Spi接口Wifi驱动分析

    前言 本文纯粹的纸上谈兵,我并未在实际开发过程中遇到需要编写或调试这类驱动的时候,本文仅仅是根据源码分析后的记录!基于内核版本:2.6.35.6 .主要是想对spi接口的wifi驱动框架有一个整体的把 ...

  5. STM32学习笔记(八) SPI总线(操作外部flash)

    1. SPI总线简介 SPI全称串行外设接口,是一种高速,全双工,同步的外设总线:它工作在主从方式,常规需要至少4根线才能够正常工作.SPI作为基本的外设接口,在FLASH,EPPROM和一些数字通讯 ...

  6. Blackfin DSP(五):BF533的SPI接口

    533SPI的特性 最高速度可达SCLK/4: 支持主模式和从模式: 可使用8个GPIO口作为从选择线: 1 slave select input pins 7 slave select output ...

  7. SPI、I2C、UART三种串行总线协议的区别和SPI接口介绍(转)

    SPI.I2C.UART三种串行总线协议的区别 第一个区别当然是名字: SPI(Serial Peripheral Interface:串行外设接口); I2C(INTER IC BUS) UART( ...

  8. Java 调用http接口(基于OkHttp的Http工具类方法示例)

    目录 Java 调用http接口(基于OkHttp的Http工具类方法示例) OkHttp3 MAVEN依赖 Http get操作示例 Http Post操作示例 Http 超时控制 工具类示例 Ja ...

  9. NUC980 运行 RT-Thread 驱动 SPI 接口 OLED 播放 badapple

    badapple 是什么,上网随便查了下,没看出个究竟,不过有个关于这个挺火的标签或者主题 < 有屏幕的地方就有 badapple >,网上有很多人用很多方式播放 badapple 动画, ...

随机推荐

  1. Java成长记录第二集--基础重点

    第一篇写的博客给自己的学习路线立了个flag后,感觉现在学习的积极性大增,这也离不开那几位老铁们的互相鼓励.废话不多说,现在给出自己总结的Java基础部分所要重点注意的内容,对以后的开发工作也是很常用 ...

  2. 搞懂 XML 解析,徒手造 WEB 框架

    恕我斗胆直言,对开源的 WEB 框架了解多少,有没有尝试写过框架呢?XML 的解析方式有哪些?能答出来吗?! 心中没有答案也没关系,因为通过今天的分享,能让你轻松 get 如下几点,绝对收获满满. a ...

  3. Gitflow分支管理策略

    Gitflow存在两个记录项目历史的分支 Master分支:存储(官方的,正式的)项目发布历史记录的分支. develop分支:充当功能的集成分支. Develop分支将包含项目的完整历史记录,而ma ...

  4. V - Largest Rectangle in a Histogram HDU - 1506

    两种思路: 1 单调栈:维护一个单调非递减栈,当栈为空或者当前元素大于等于栈顶元素时就入栈,当前元素小于栈顶元素时就出栈,出栈的同时计算当前值,当前值所包含的区间范围为从当前栈顶元素到当前元素i的距离 ...

  5. B - Cow Marathon DFS+vector存图

    After hearing about the epidemic of obesity in the USA, Farmer John wants his cows to get more exerc ...

  6. 一起了解 .Net Foundation 项目 No.24

    .Net 基金会中包含有很多优秀的项目,今天就和笔者一起了解一下其中的一些优秀作品吧. 中文介绍 中文介绍内容翻译自英文介绍,主要采用意译.如与原文存在出入,请以原文为准. Xamarin.Mobil ...

  7. 图2-4TCP状态转换图

    这张图中描述了TCP中11个状态的转换. 光看这个图我一开始是蒙蔽的,也没有写服务器和客户端的操作流程.不过回头一想,是状态转换,也就是从一个状态到另外一个状态发生了什么,什么条件触发的.这样是不是好 ...

  8. PHP 常用数组的具体运用?常用吗?

    在 PHP 中,有三种类型的数组: 数值数组 - 带有数字 ID 键的数组 关联数组 - 带有指定的键的数组,每个键关联一个值 多维数组 - 包含一个或多个数组的数组 看具体实例: 创建数组 < ...

  9. 2019-2020-1 20199326《Linux内核原理与分析》第七周作业

    实验内容:分析Linux内核创建一个新进程的过程 初始化Menu Os,输入fork可以看到menuos触发了一个fork系统调用 再开一个shell,进入调试模式,设置几个断点sys_clone,d ...

  10. Makefile: missing separator(did you mean TAB instead of 8 spaces?). Stop.

    通常我们会对vimrc文件加以配置(如将TAB键自动转换为4个空白键). 但正是由于将tab键转换为n个空白键,使得用vim编写的Makefile中不存在tab键(即“\t”)了.恰恰Makefile ...