|
本帖最后由 兔包公 于 2023-8-1 15:33 编辑
书接上回,今日点亮后,再总结废话一帖,第二回书说到,还有2成要完成,汉字,ASCII码,图片的取模和显示,先把这预留的作业搞定了再废其他。
第一回,记一次失败的尝试,用STC15W4K56S4点亮农行金e顺通用K宝12864屏(排线丝印FM1420901CT06-00-B)
第二回,点屏再战记,成功用STC15W4K56S4点亮广发银行蓝牙key盾12864屏
第三回,也来探讨下点屏大战过程中的遇到的玄学问题
一点零碎小记:
①一般情况下常见的1个字符我们需要16*8个点(8*8),1个汉字16*16个点,放在12864屏幕中才能完美显示,,可以形象的想象一下作文本中的一个个格子,假如把这些格子变得很小很小,你咋写字?就算你牛13写的下,那也无非是天书谁看的懂?放在12864中就是需要2页中的8列,2页中的16列,那么取模的过程就是把字符,汉字按照12864里每个LED灯的亮灭用16进制数据表示出来,我们再把这些数据放进一个数组里,后期调用时直接按照顺序写这些数据到12864,便可显示对应的字符,汉字。另外根据页扫描和列扫描方向的不同,取模的数据也不同,一般情况下都会按照书写习惯,从上到下,从左到右的方式,初始化往12864写命令时要把这2个命令写上,要不然默认是反的,xy轴都是镜像的。
②有字库和无字库的LCD屏的区别:似乎也可以简单理解为有字库的就是把这些16进制数据寄存在了一个叫HCGROM的地方,再通过ASCII码表格的形式映射出来,你想显示什么字符你只要告诉我字符在ASCII表格中的位置,我会把这些16进制数据自动送去DDRAM处理显示。
③取模软件,数量众多,大同小异,这里就按照坛友分享的这款为例。发个取字模软件PCtoLCD2002完美版大字版的
结合ST7565手册中下图,按列从左到右,按页从上到下,那对应取模方式列行式(横向取模,一列一列形成行,形成页),取模走向(低位在前)应该就是说取出来得16进制数据是红色箭头指向可见D0到D7,D0位最低位是在最上的。
④显示程序过程就不说,1个1个显,还是指定坐标显,还是整屏显,基本按需求自行配备合来,定义个指针指向取模数组,编就行了。图片显示一样道理,形象的说相当于把多个点组合表示图片,一样的用法,我是先弄图片显示的,过程编译时老报错,太久没耍了忘记用code这关键字了,哎。
另大婶@jf201006分享的这贴里也有取模的相关介绍。
串行通信之SPI协议、IIC协议实践,点亮两个12864液晶屏/U盾
测试效果:数码之家图片, 字符,汉字搞定了。
程序txt格式的,一个c文件直接搞定先,ASCII数据直接捡坛友分享够了,还是那句话是只猴子,天生会偷桃。后期再来化整为零,模块化,方便调用,另外我还看到有人用结构体struct写的程序,看起来有点像Python里的对象用法,哪天心血再来潮,再来研究。
≠====≠========================≠=≠≠===========
第二把,子丑寅卯,申已午未,点中谁,就是谁,这把又是哪个挨野?还是那堆u盾,这把就是你了,光大家的,光大,光大,日日光,月月头都大的玩意,3下5/2,4零8落,分离。
屏排线7个脚位,屏排线丝印:FG12864N-03744,呀!这个-后面的数字003744竟然和上回广发的一样呢,同一驱动的概率很高呀。这个屏就不需要再去什么查排线到芯片,定义引脚,因为也是直接可以就捡现成的了,还是前人种树后人吃果,这位坛友在此帖已经给出了,拆个金融@家工行U盾,并尝试点亮
虽然不是一家银行的,但我严重怀疑这些个u盾都是一家代工厂生产的,要不用的什么物料都一样呢?上把忘记贴上的图,这回一样可以用,这主控也是同一家的公司,型号不同而已,引脚估计有点差别,与屏幕连接脚位有差别。
上回书有人回复说用STC的硬件SPI通信,那这回就耍耍这SPI,还是大婶@jf201006的分享,学习一下常用的串行通信协议(UART/IIC/SPI)此帖我认为讲的已经很透彻。这里简单简单通俗一点来说一下就得了,就问你看过扇耳光比赛没有?没看过的请先看下下图。
好的,记住这个画面,那么现在看到STC15系列的芯片手册这里,第15章专门有介绍SPI通信的,目前我们是单主机一从机的通信模式,单片机和12864,那就选取2个图来看
①要进行相互通信最主要的就是靠这个移位寄存器了,这就是跟互相打耳光一样色的,你扇一下,我扇一下,形成2个设备的数据传输。至于扇上面1点还是下面1点,就是我们高低位选择了,先高还是先低。
②这里讲到个词叫全双工,那就升级一下比赛,就好比一声令下,同一时间打对方耳光。
③那么数据缓冲区就好比双方打了8下耳光后各自给对方留下的痕迹,也可以说是我要什么打对方让对方更疼的数据,8下意思就是8位数据,具体情况具体来就是了。
④至于那些什么SPI控制寄存器,管脚控制,时钟逻辑这些,就是站边上的教练了,教练就是控制或者说指挥你什么打耳光的,哪个时间段打,用哪只手打,中途来电话了什么办之类的。这些教练可都是死脑袋,天天吃饱不干活的,这时候就需要我们要写程序来敲下这些脑壳就行了。
⑤当然了,你可别随便上大街就给人来一耳光,那大概率可是要被阿sis请喝咖啡的,这一切的前提都是有主办方可以办这个打耳光比赛,双方自愿且合规的情况下。这就是所说主从机提供什么样的接口通信我们也才能用。
接下来还是一样的把大象装进冰箱,一步一步来憋,这也是c语言的一大特点。当初不知道是谁教我的,不需要去记这些个什么寄存器的控制位呀咋功能的呀,用到的时候对着数据手册看着来就得了,我也是傻傻听他的了,一个也没记,现在想想当初要是认真一点,努力一点,那怕记1两个呢,也不至于现在只能慢慢对着来呀。寄存器地址一般在头文件里有定义,不是用STC头文件的使用前要先声明再使用,正所谓此路是我开,要从此路过,留下买路财。
这几个寄存器中,上图框选中的那些,这把操作目前暂时用不到,那就来讲讲这用不到的先吧,这都是与中断相关的外部中断,定时器中断等之类的,所谓中断很好理解,就上文说的来电话了一样,再通俗一点就是,打比如吧,二口子正在洞房花烛,搞事情,这时哎,闹洞房的来敲门了,你说什么办好?正又赶巧了,此时,门外又来报,说是老爷子同一天就要2眼一闭归西了,要见最后一面又什么办?这就是IE中断,闹洞房的和老爷子就好比是ET,ES这些个中断位。取1代表这些事情可以来打断,反之亦然,2口子找了个安静的无人打扰的地搞事情。EA位叫总开关,关了咋事中断都不管,也可以说新郎官起码得是个活人的才能去处理这些事情,事还没办呢,人没了,多悲哀呀。
IP中断优先级,这里面些的位就是定义我们先去处理哪个问题先了,是先去给闹洞房的派红包还是先去见老爷子,或者是不管3721起来吃片肾宝片,继续搞完事情先才说。
那些用到的也是没想好什么废,STC数据手册里解析的够清楚的了,对照着来一看就会了,这里原先是想一位一位的定义,写完最后发觉STC头文件没有定义这些位,不可位寻址的另说,但这也不是呀,上回书有人回复的程序,开头宏定义取值完,一条语句直接搞定,新手也来耍耍原地飙车。
挑个重点的来吧,这里时钟相位CPHA和时钟极性CPOL的不同决定了4种数据传输模式中sclk的状态,也可以大概理解为sclk在什么时候传输的数据被采集,被认为有效。再打个比如吧,耳光打到脸上,有的人立马感觉到疼了,而有的人要反应一下等你把手收回来,或者抬起来才感觉到热辣滚烫,手开始打之前的摆放位置就是说的时钟前沿。
本次结合各网友分享的贴中和上回书中ST7565串行时序图,3个橙色框起来的,是不是一样,而且ST7565手册中(红框处)也有提到,数据是在上升沿时被检测,可见时序图中的黑色箭头。多方结合那么就是MOOD3传输模式,还能跑哪去不成,也就CPHA=1,CPOL=1。
差不多了,开搞,按需求连接引脚,为避免大力出奇迹,还是透明胶粘下。
这把有长进了,主要也有引脚间距够。大婶们,请问一下这种排线,一般你们是飞上层焊点还是下层的??
写好,编译,排错,下载,来来回回都是一样的操作,掉坑卡壳,最后还是出来了,各种玄学问题已解决。就再问这把亮了没有??当然是亮了,要不那不白废那么多口水干嘛。还是一样,横线,竖线,全屏点亮,熄灭清屏测试。
最后总结SPI大概流程:
①配置IO口为准双向(首次尝试就是掉这坑里)
②配置AUXR1(P_ SW1)引脚功能切换寄存器(本次使用默认引脚,忽略)
③配置SPCTL控制寄存器(各个位的取值)
④配置IE,IE2,IP2中断相关寄存器(本次不用,忽略)
⑤SPDAT数据寄存器初始化(取0)
⑥SPSTAT状态寄存器,2个标志位写1清0
⑦SPDAT取值写读数据,判断标志,成功与否,再写1清(本次只管写,不读,也没有读可以选择)
就这样,收工,谢谢观看。
=====================我是分割线=========================
=============代了个码===================
- /*================================*/
- /* 硬件SPI点屏测试 */
- /* 2023.7.28 D206 */
- /* 目前状态 : */
- /*操作成功 !(2023-08-01 09:13:47)*/
- /*==============================*/
- #include <STC15.H> //头文件,直接STC-ISP添加到keil
- #include "intrins.h" //库函数,以便调用空函数延时用
- //宏定义
- typedef unsigned int uint;
- typedef unsigned char uchar;
- #define SSIG 0x80 //SPCTL.7 取1,SS引脚忽略控制位,由MSTR确定主从机
- #define SPEN 0x40 //SPCTL.6 取1,SPI使能
- #define DORD 0x00 //SPCTL.5 取0,最高位先发送
- #define MSTR 0x10 //SPCTL.4 取1,主机选择
- #define CPOL 0x08 //SPCTL.3 时钟极性,取1,组成MOOD3
- #define CPHA 0x04 //SPCTL.2 时钟相位,取1,组成MOOD3
- #define SPDHH 0x00 //SPCTL.1 SPCTL.0 时钟分频,CPU_CLK/4:默认值
- #define SPDH 0x01 //CPU_CLK/8
- #define SPDL 0x02 //CPU_CLK/16
- #define SPDLL 0x03 //CPU_CLK/32
- #define SPIF 0x80 //SPSTAT.7 传输完成标志位,软件写1清0
- #define WCOL 0x40 //SPSTAT.6 写冲突标志位,软件写1清0
- sbit CS = P1^2; //片选使能脚
- sbit RST = P1^7; //复位脚
- sbit A0 = P1^6; //数据或指令选择脚,也有叫RS
- //sbit SCLK = P1^5; //时钟脚
- //sbit SDA = P1^3; //数据脚,也有叫SI,DO
- /*延时函数,直接从stc-isp里自动生成*/
- void Delay1000ms() //@11.0592MHz
- {
- uchar data i, j, k;
- _nop_();
- _nop_();
- i=43;
- j=6;
- k=203;
- do
- {
- do
- {
- while (--k);
- } while (--j);
- } while (--i);
- }
- void Delay5ms() //@11.0592MHz
- {
- uchar data i, j;
- i=54;
- j=199;
- do
- {
- while (--j);
- } while (--i);
- }
- void Delay200ms() //@11.0592MHz
- {
- uchar data i, j, k;
- _nop_();
- _nop_();
- i=9;
- j=104;
- k=139;
- do
- {
- do
- {
- while (--k);
- } while (--j);
- } while (--i);
- }
- /*初始化SPI函数*/
- void SpiInit()
- {
- SPDAT=0x00;//数据寄存器初始化
- SPSTAT=SPIF|WCOL;//清除SPI状态
- SPCTL=SSIG|SPEN|MSTR|CPOL|CPHA|SPDHH;//使能主机模式
- }
- /*SPI发送数据函数*/
- /*参数dat:一个字节*/
- void SpiSendByte(uchar dat)
- {
- SPDAT=dat;
- while(!(SPSTAT&SPIF));//等待发送完成
- SPSTAT=SPIF|WCOL;//软件写1,清除标志位
- }
- /*写指令到LCD12864函数*/
- /*参数cmd:命令字节 */
- void LcdWriteCommand(uchar cmd)
- {
- CS=0; //片选脚使能
- A0=0; //低电平传的是指令
- SpiSendByte(cmd);
- CS=1; //传完,使能停止
- }
- /*写数据到LCD12864函数*/
- /*参数byte:数据字节 */
- void LcdWriteData(uchar byte)
- {
- CS=0; //同上
- A0=1; //高电平传的是数据
- SpiSendByte(byte);
- CS=1;
- }
- /*LCD12864初始化函数*/
- void LcdInit()
- {
- RST=1;
- Delay5ms();
- RST=0;
- Delay5ms();
- RST=1;//复位脚,高电平复位
- Delay200ms();
- LcdWriteCommand(0xE2); //软复位
- LcdWriteCommand(0x23); //电阻比,对比度粗调
- LcdWriteCommand(0x81); //对比度精调,双指令,必须跟下面一条连着
- LcdWriteCommand(0x2D); //对比度精调取值,双指令,必须跟上面一条后面,此参数根据屏幕不同设置不同
- LcdWriteCommand(0x2F); //电源升压设置,(Ox2E)
- LcdWriteCommand(0xA0); //列扫描顺序:从左到右
- LcdWriteCommand(0xC8); //页扫描顺序:从上到下
- LcdWriteCommand(0xAF); //显示:开
- Delay5ms();
- Delay5ms();
- }
- /*显示测试函数 */
- void LcdTest(uchar ph,uchar pl)
- {
- uchar page,column;
- for(page=0;page<8;page++)
- {
- LcdWriteCommand(0xB0+page);//设置页地址
- LcdWriteCommand(0x10); //设置列地址高4位
- LcdWriteCommand(0x00); //设置列地址低4位
- for (column=0;column<64;column++)
- {
- LcdWriteData(ph);
- LcdWriteData(pl); //连续写入2个字节数据,128/2=64,循环64次
- }
- }
-
- }
- /*主函数*/
- void main()
- {
- P1M0=0x00;
- P1M1=0x00;//设置P1口为准双向
- SpiInit();
- LcdInit();
- while(1)
- {
- LcdTest(0x00,0x00); //清屏,全屏熄灭
- Delay1000ms();
- LcdTest(0xFF,0x00); //测试竖线
- Delay1000ms();
- LcdTest(0x00,0x00);
- Delay1000ms();
- LcdTest(0x00,0xFF); //换列测试
- Delay1000ms();
- LcdTest(0x00,0x00);
- Delay1000ms();
- LcdTest(0x55,0x55); //测试横线
- Delay1000ms();
- LcdTest(0x00,0x00);
- Delay1000ms();
- LcdTest(0xAA,0xAA); //换行测试
- Delay1000ms();
- LcdTest(0x00,0x00);
- Delay1000ms();
- LcdTest(0xFF,0xFF); //全屏点亮测试
- Delay1000ms();
- }
- }
-
复制代码
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
打赏
-
查看全部打赏
|