神农鼎
发表于 2023-11-6 15:24:32
实验箱中 I2C/SPI-OLED12864的电路
核心功能实验板中 I2C/SPI-OLED12864的电路
浦江一水
发表于 2023-11-6 15:30:55
本帖最后由 浦江一水 于 2023-11-6 15:49 编辑
实验 STC32G12K128 自制实验板驱动彩色显示屏
日前实验了驱动OLED_IIC单色显示屏, 自然是不会满足于现状的,如今再弄个彩色的显示屏,驱动它一下试试看…………
淘了一块1.8寸128*160像素的彩色显示屏。RMB 11.5元。八针引脚,ST7735驱动。
还是这块DIP40的自制实验板,还是用原来LCD1602的接口,利用背光电源+和地-两脚,加上原来的P0数据口,将八脚的彩色显示屏反过来插, 正好插入。
。。。。
从上图已经可见, 驱动实验是成功的,学习是有收获的,给生活是增添乐趣的。
(利用一个接口排列, 实验多种外设的练习,这一点使人联想到正如管理员在楼上贴出的实验箱接口的多种变化使用,在构思上是有一点巧妙之处的。)
浦江一水
发表于 2023-11-6 16:13:20
这次实验体现几个内容:
1,实现对ST7735彩色显示屏的显示控制:前景背景色变化,西文字符串显示,16点阵和24点阵中西文混合显示;
2,体验STC32G12K128的12位ADC转换的算法和效果;
4,四键八值的使用。
上电后。。。。出现如图:
体现了24点阵中西文混合显示的效果。
按任意键继续。。。出现如图:
此时,短按K4键,提示“KEY=40”。(若长按K4,提示“KEY=41”。K1..K3键状态依此类推………… 体验四键八值的使用效果。)
屏幕上: 红底黄字"STC单片机” 体现了16点阵中西文混合显示效果。
除顶行标题之外,
首行显示:实测通道CH15内部1190mv的ADC值,
二行显示:实测通道CH03外接电位器输入电压的ADC值,
三行显示:经过计算的通道CH03的电压mv值 。
浦江一水
发表于 2023-11-6 18:08:09
主程序源码: 编程思路与理解思考写在注释中。。。
//========================================================
// 1.8" TFT 彩色显示屏 160*128 实验程序
// 驱动: ST7735
// 基于: STC32G12K128芯片实验板编程 主频选择: 22.118400MHz
// 整理编程: 浦晓明(浦江一水)2023-10 for国芯论坛
//========================================================
#include "STC32G.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "KEY4_IO.H"
#include "LCD_7735.H"
#include "ADC.H"
//数据类型定义
#define u8unsigned char
#define u16 unsigned int
#define u32 unsigned long
//4LED
sbit LED0= P2^0;//运行指示
sbit LED1= P2^1;//运行指示
sbit LED2= P2^2;//运行指示
sbit LED3= P2^3;//运行指示
// 全局变量
unsigned char k; //键值
char S; //显示缓存
unsigned int ADC15,ADC03,ADCmv;//ADC转换变量
unsigned char Mode=0; //模式字
//非精确延时函数
void Delayms(unsigned int count)
{ unsigned int i,j;
for(i=0;i<count;i++)
for(j=0;j<500;j++);
}
//主程序入口
void main(void)
{ unsigned short wait=0,i=0;
//IO端口初始化
WTST= 0; //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
//IO端口初始化//全部为双向口
P0M1 = 0x00; P0M0 = 0x04; //设置为准双向口: P0.2推挽输出控制背光
P1M1 = 0x00; P1M0 = 0x00; //设置为准双向口
P2M1 = 0x00; P2M0 = 0x00; //设置为准双向口
P3M1 = 0x00; P3M0 = 0x00; //设置为准双向口
P4M1 = 0x00; P4M0 = 0x00; //设置为准双向口
P5M1 = 0x00; P5M0 = 0x00; //设置为准双向口
LCD_Init(); //显示屏初始化
CLS(1); //蓝色背景清屏
LineH(0,29,128,12); //测试画线函数
H24(10,3,"STC单片机",11,1); //中西文混合字符串显示
GETCH(); //按任意键继续
CLS(1); //蓝色背景清屏
Point(0,16,0); //测试画点函数
LineH(0,16,128,12); //测试画线函数(红色水平线)
Box(0,140,128,20,0,0,0); //测试画矩形块函数(黑色矩形-底部状态栏)
A16(0, 0,"Test_ADC_(12Bit)",15,1,16);//标题(蓝色底白色字)
A16(0,30,"CH15_ADC=",15,1,9); //通道15,ADC转换字(0--4095)
A16(0,50,"CH03_ADC=",15,1,9); //通道03,ADC转换字(0--4095)
A16(0,70,"CH03ADmv=",15,1,9); //通道03,计算为mv值
A8(0,90,"Mode=0",14,1,6); //求平均模式
A12(0,144,"KEY=",31,0,4); //显示键值
H16(4,110," STC32G 单片机 ",14,4); //中西文混合字符串显示, 源代码直接书写,增强源码可读性
ADC_Init(); //ADC初始化
while(1)
{ wait++; //间歇延时循环计数
sprintf(S,"%03d",wait); A16(96,142,S,15,1,3);
if(wait==100)
{ wait=0;
switch(Mode)
{ case 0: ADC15=Get_ADC12bitResult(15); //读一次通道15内部电压
ADC03=Get_ADC12bitResult(3); //读一次通道03内部电压,外部电位器调节输入电压
break;
case 1: ADC15=0;ADC03=0;
for(i=0;i<16;i++){ ADC15 += Get_ADC12bitResult(15);Delayms(5000); } //读16次内部基准电压
ADC15=ADC15>>4; //求平均
for(i=0;i<16;i++){ ADC03 += Get_ADC12bitResult(3); Delayms(5000); } //读16次外部电压
ADC03=ADC03>>4; //求平均
break;
case 2: ADC03=0;
for(i=0;i<16;i++){ ADC03 += Get_ADC12bitResult(3); Delayms(5000); }
ADC03=ADC03>>4;
break;
}
ADCmv=(u16)((u32)ADC03 * 1190 / ADC15); //计算外部电压, Bandgap为1190mV, 测电压分辨率1mV
sprintf(S,"%04d",ADC15); A16(80,30,S,10,1,4); //组织待显示通道15ADC转换字的字符串, 并用16点阵ASC字符串的显示方式显示之.
sprintf(S,"%04d",ADC03); A16(80,50,S,10,1,4); //组织待显示通道03ADC转换字的字符串, 并用16点阵ASC字符串的显示方式显示之.
sprintf(S,"%04d",ADCmv); A16(80,70,S,10,1,4);//组织待显示通道03转换后计算电压mv值,并用16点阵ASC字符串的显示方式显示之.
}
k=0; k=RDKEY(); //扫描按键...
if(k!=0) //如果有键按下...
{ sprintf(S,"KEY=%2X",k);//用16进制数模式显示键值
A12(0,144,S,31,0,6); //显示键值...
if(k==0x40) //如果是短按K4
{ Mode=Mode<2?Mode+1:0;//模式切换.观察ADC不同算法效果比较..
sprintf(S,"Mode=%1d",Mode);
A16(0,90,S,14,1,6); //显示模式...
GETCH(); //暂停..按任意键继续...
}
} Delayms(100); //延时...循环...
}
}
//***** END *************************************************************************************************
浦江一水
发表于 2023-11-6 19:57:33
本帖最后由 浦江一水 于 2023-11-6 20:20 编辑
TFT 1.8 寸 彩色显示屏相关文件 -- 头文件
//========================================================
// 文件: LCD_7735.H头文件
// 功能: ST7735 TFT 1.8" 彩色显示屏(160*128)驱动程序
// 基于: STC32G12K128芯片实验板编程 主频选择: 22.118400MHz
// 编程: 浦晓明(浦江一水) 2023-10 PXM for 国芯论坛
//========================================================
#include "STC32G.h"
#ifndef __LCD_7735_H_
#define __LCD_7735_H_
//========================================================
//函数说明
void LCD_Init(void); //显示屏初始化
void LCD_CLS(unsigned short color); //指定色清屏
void LCD_SetBox(unsigned char X,unsigned char Y,unsigned char W,unsigned char H);//设置显示窗口,XY坐标WH宽高
void LCD_BMP(unsigned char X,unsigned char Y,unsigned char W,unsigned char H,unsigned char * pic); //显示BMP图片
// 以下函数与其它显示屏驱动函数定义相同.方便使用和移植..
void CLS(unsigned char Bcolor); /* 初始化清屏函数.调用参数:背景色 */
void MoveTo(unsigned short X,unsigned short Y); /* 移动点坐标(转换成显存地址) */
void Point(unsigned short X,unsigned short Y,unsigned char Color);/* 单独画一彩色点函数 */
void Box(unsigned short X,unsigned short Y,unsigned short H,unsigned short V,unsigned char C1,unsigned char C2,unsigned char BC);/* 画彩色矩形方框函数 */
void LineH(unsigned short X,unsigned short Y,unsigned short H,unsigned char Color); /* 画水平彩色直线函数 */
void LineV(unsigned short X,unsigned short Y,unsigned short V,unsigned char Color); /* 画垂直彩色直线函数 */
void Line(unsigned short X1,unsigned short Y1,unsigned short X2,unsigned short Y2,unsigned char Color); /* 任意两点画直线函数 */
void A8( unsigned short X,unsigned short Y,char *str,unsigned char Fcolor,unsigned char Bcolor,unsigned char Len); /* 6*8点阵西文字符显示 */
void A12(unsigned short X,unsigned short Y,char *str,unsigned char Fcolor,unsigned char Bcolor,unsigned char Len); /* 12点阵西字符显示 */
void A16(unsigned short X,unsigned short Y,char *str,unsigned char Fcolor,unsigned char Bcolor,unsigned char Len); /* 16点阵西文字符显示 */
void A24(unsigned short X,unsigned short Y,char *str,unsigned char Fcolor,unsigned char Bcolor,unsigned char Len); /* 24点阵西文字符显示 */
void H16(unsigned short X,unsigned short Y,char *str,unsigned char Fcolor,unsigned char Bcolor); /* 16点阵中西文混合字符串显示 */
void H24(unsigned short X,unsigned short Y,char *str,unsigned char Fcolor,unsigned char Bcolor); /* 24点阵中西文混合字符串显示 */
#endif
//========================================================
浦江一水
发表于 2023-11-6 20:16:17
本帖最后由 浦江一水 于 2023-11-7 16:16 编辑
TFT 1.8 寸 彩色显示屏相关文件 -- 函数实现 .C 文件
//========================================================
// 文件: LCD_7735.C 函数实现
// 功能: ST7735 TFT 1.8" 彩色显示屏(160*128)驱动程序
// 基于: STC32G12K128芯片实验板编程 主频选择: 22.118400MHz
// 编程: 浦晓明(浦江一水) 2023-10 PXM for 国芯论坛
//========================================================
#include "STC32G.h"
#include <stdio.h>
#include <string.h>
#include "LCD_7735.H" //显示屏驱动函数说明头文件
#include "ASCII.H" //西文ASCII字符点阵模头文件
#include "LCD_HZK.H" //中文16点阵/24点阵汉字点阵模头文件
//数据类型定义
#define u8 unsigned char
#define u16 unsigned short
#define u32 unsigned int
//屏幕像素说明
#define Height 160 //高
#define Width128 //宽
//RGB_565_16位色彩定义(参考定义,实际不使用)
#define RED 0xF800 //红色
#define GREEN 0x07E0 //绿色
#define BLUE 0x001F //蓝色
#define YELLOW 0xFFE0 //黄色
#define WHITE 0xFFFF //白色
#define BLACK 0x0000 //黑色
#define PURPLE 0xF81F //紫色
/* 32彩色表色号定义自定义彩色编号 0..15编号参照UCDOS系统定义 */
unsigned short code COLOR[]={
0x0000, //0黑色00000 000000 00000
0x1048, //1蓝色00010 000010 01000
0x1442, //2绿色00010 100010 00010
0x1452, //3青色00010 100010 10010
0x9042, //4红色10010 000010 00010
0x9052, //5紫色10010 000010 10010
0xA484, //6橙色10100 100100 00100
0x8410, //7灰色10000 100000 10000
0xC618, //8亮灰11000 110000 11000
0x001F, //9亮蓝00000 000000 11111
0x07E0, //10亮绿
0x07FF, //11亮青0000 0111 1111 1111
0xF800, //12亮红
0xF81F, //13亮紫
0xFFE0, //14黄色
0xFFFF, //15白色
0x2104, //16深灰//16...31 编号参照Windows画图板
0x0006, //17暗蓝
0x79EF, //18浅紫
0x8408, //19土黄
0x0180, //20暗绿 0000 0001 1000 0000
0x041F, //21河蓝
0x0210, //22蓝黑
0x801F, //23紫色
0x8200, //24咖啡
0xF81F, //25亮紫
0xFFF0, //26浅黄
0x0700, //27翠绿 0000 0111 0000 0000
0xC7FF, //28亮青 1100 0111 1111 1111
0x841F, //29青灰
0xF810, //30殷红
0xFC08, //31橙色
};
//================================================================
// 接口定义: 利用LCD1602接口(反相排序)(根据实际电路板情况定义)
// 1602:K- A+D7D6D5D4D3D2 D1 D0 E WR RS Vo VCC GND
// OLED: GND VCC SCL SDA RES DCCSBL
//================================================================
sbit SCL = P0^7;//时钟端
sbit SDA = P0^6;//数据端
sbit RES = P0^5;//复位端 0:复位
sbitDC= P0^4;//0:指令/1:数据
sbitCS= P0^3;//片选 0:选中
sbitBL= P0^2;//背光 0:灭 1:亮
//========================================================
//函数说明
void delay(u16 count); //延时
void LCD_WR_CMD(u8 Cmd); //写命令
void LCD_WR_DAT(u8 Dat); //写数据
//========================================================
// 非精确延时函数
//========================================================
void delay(u16 count)
{ unsigned int i,j;
for(i=0;i<count;i++)
for(j=0;j<500;j++);
}
//========================================================
// LCD 接口写一字节数据基本内部函数
//========================================================
void WriteByte(u8 Byte)
{ int i;
for(i=0;i<8;i++)
{ if(Byte &0x80)SDA=1;
else SDA=0;
SCL=0;
SCL=1;
Byte<<=1;
}
}
//========================================================
// 写命令基本函数 8位数 一字节
//========================================================
void LCD_WR_CMD(u8 Cmd)
{
CS=0;
DC=0;
WriteByte(Cmd);
CS=1;
}
//========================================================
// 写数据令基本函数 8位数 一字节
//========================================================
void LCD_WR_DAT(u8 Dat)
{
CS=0;
DC=1;
WriteByte(Dat);
CS=1;
}
//========================================================
// 写数据令基本函数 16位数 2字节
//========================================================
void LCD_WR_DATA(u16 Data)
{
CS=0; //片选
DC=1;//写数据
WriteByte((u8)(Data/256));
WriteByte((u8)(Data%256));
CS=1;
}
//========================================================
// 显示屏初始化 (参考厂方提供的初始化程序代码)
//========================================================
voidLCD_Init(void)
{
//--ST7735R Reset Sequence-- 复位
RES =0; delay(120);//Delay 120ms
RES =1; delay(100);//Delay 100ms
//--End ST7735S Reset Sequence--
LCD_WR_CMD(0x11);//Sleep out
delay(120); //Delay 120ms
//--ST7735S Frame Rate--
LCD_WR_CMD(0xB1); LCD_WR_DAT(0x01); LCD_WR_DAT(0x2C); LCD_WR_DAT(0x2D);
LCD_WR_CMD(0xB2); LCD_WR_DAT(0x01); LCD_WR_DAT(0x2C); LCD_WR_DAT(0x2D);
LCD_WR_CMD(0xB3); LCD_WR_DAT(0x01); LCD_WR_DAT(0x2C); LCD_WR_DAT(0x2D);
LCD_WR_DAT(0x01); LCD_WR_DAT(0x2C); LCD_WR_DAT(0x2D);
//--End ST7735S Frame Rate--
LCD_WR_CMD(0xB4); LCD_WR_DAT(0x07); //Dot inversion
//--ST7735S Power Sequence--
LCD_WR_CMD(0xC0); LCD_WR_DAT(0xA2); LCD_WR_DAT(0x02); LCD_WR_DAT(0x84);
LCD_WR_CMD(0xC1); LCD_WR_DAT(0xC5);
LCD_WR_CMD(0xC2); LCD_WR_DAT(0x0A); LCD_WR_DAT(0x00);
LCD_WR_CMD(0xC3); LCD_WR_DAT(0x8A); LCD_WR_DAT(0x2A);
LCD_WR_CMD(0xC4); LCD_WR_DAT(0x8A); LCD_WR_DAT(0xEE);
//--End ST7735S Power Sequence--
LCD_WR_CMD(0xC5); LCD_WR_DAT(0x0E); //VCOM //1a
LCD_WR_CMD(0x36); LCD_WR_DAT(0xC0); //LCD_WR_DAT(0xC0);竖屏 // LCD_WR_DAT(0xA8); 横屏//MX, MY, RGB mode
//--ST7735S Gamma Sequence--
LCD_WR_CMD(0xE0); LCD_WR_DAT(0x0F); LCD_WR_DAT(0x1A); LCD_WR_DAT(0x0F); LCD_WR_DAT(0x18);
LCD_WR_DAT(0x2F); LCD_WR_DAT(0x28); LCD_WR_DAT(0x20); LCD_WR_DAT(0x22);
LCD_WR_DAT(0x1F); LCD_WR_DAT(0x1B); LCD_WR_DAT(0x23); LCD_WR_DAT(0x37);
LCD_WR_DAT(0x00); LCD_WR_DAT(0x07); LCD_WR_DAT(0x02); LCD_WR_DAT(0x10);
LCD_WR_CMD(0xE1); LCD_WR_DAT(0x0F); LCD_WR_DAT(0x1B); LCD_WR_DAT(0x0F); LCD_WR_DAT(0x17);
LCD_WR_DAT(0x33); LCD_WR_DAT(0x2C); LCD_WR_DAT(0x29); LCD_WR_DAT(0x2E);
LCD_WR_DAT(0x30); LCD_WR_DAT(0x30); LCD_WR_DAT(0x39); LCD_WR_DAT(0x3F);
LCD_WR_DAT(0x00); LCD_WR_DAT(0x07); LCD_WR_DAT(0x03); LCD_WR_DAT(0x10);
LCD_WR_CMD(0x2A); LCD_WR_DAT(0x00); LCD_WR_DAT(0x00); LCD_WR_DAT(0x00); LCD_WR_DAT(0x80);//宽度128
LCD_WR_CMD(0x2B); LCD_WR_DAT(0x00); LCD_WR_DAT(0x00); LCD_WR_DAT(0x00); LCD_WR_DAT(0xA0);//高度160
LCD_WR_CMD(0xF0); LCD_WR_DAT(0x01);//Enable test command
LCD_WR_CMD(0xF6); LCD_WR_DAT(0x00);//Disable ram power save mode
//LCD_WR_CMD(0x2C);
//--End ST7735S Gamma Sequence--
LCD_WR_CMD(0x3A); LCD_WR_DAT(0x05); //65k mode
LCD_WR_CMD(0x29); //Display on 显示开
BL=1; //背光亮
}
//========================================================
// 设置显示窗口: X,Y左上坐标,W宽,H高
//========================================================
void LCD_SetBox(unsigned char X,unsigned char Y,unsigned char W,unsigned char H)
{
LCD_WR_CMD(0x2A); LCD_WR_DAT(0); LCD_WR_DAT(X); LCD_WR_DAT((u8)(X+W-1)); LCD_WR_DAT((u8)(X+W-1));
LCD_WR_CMD(0x2B); LCD_WR_DAT(0); LCD_WR_DAT(Y); LCD_WR_DAT((u8)(Y+H-1)); LCD_WR_DAT((u8)(Y+H-1));
LCD_WR_CMD(0x2C);
}
//========================================================
// 指定色清屏 Color (16位 RGB 色)
//========================================================
void LCD_CLS(unsigned short Color)
{ int i,j;
LCD_SetBox(0,0,128,160);
for (i=0;i<Height;i++)
{ for (j=0;j<Width; j++)
LCD_WR_DATA(Color); //16位数据
}
}
//========================================================
// 显示图片 BMP图片
//========================================================
void LCD_BMP(unsigned char X,unsigned char Y,unsigned char W,unsigned char H,unsigned char * pic)
{u16 i;
u8 h,l;
LCD_SetBox(X,Y,W,H); //设置显示窗口
for(i=0;i<W*H;i++)
{ l=pic; h=pic;//图像数据:低位在前/高位在后
LCD_WR_DAT(h); //显示彩色点(高位在前)
LCD_WR_DAT(l); //显示彩色点(低位在后)
}
LCD_SetBox(0,0,Width,Height);//恢复全屏区域
}
/*===========================================================================
** 函数名称: CLS(unsigned int Color)
** 功能描述: 对LCD进行初始化 同时用某色清屏
============================================================================*/
void CLS(unsigned char Bcolor)
{ u16 temp;
LCD_WR_CMD(0x2A);LCD_WR_DAT(0x00);LCD_WR_DAT(0x00);LCD_WR_DAT(0x00);LCD_WR_DAT(0x80); //设置水平GRAM起止地址
LCD_WR_CMD(0x2B);LCD_WR_DAT(0x00);LCD_WR_DAT(0x00);LCD_WR_DAT(0x00);LCD_WR_DAT(0xA0); //设置垂直GRAM起止地址
LCD_WR_CMD(0x2C); //LCD_WR_Start();
for (temp = 0; temp < 20480; temp++) LCD_WR_DATA(COLOR); //128*160*2=40960
}
/*===========================================================================
** 移动点坐标(转换成显存地址,并做好读写数据准备).
** 调用参数: X列(0--159) Y行(0--127)
============================================================================*/
void MoveTo(unsigned short X,unsigned short Y)
{
LCD_WR_CMD(0x2A); LCD_WR_DAT((u8)(X/256)); LCD_WR_DAT((u8)(X%256)); LCD_WR_DAT(0x00); LCD_WR_DAT(0x80);//定X坐标
LCD_WR_CMD(0x2B); LCD_WR_DAT((u8)(Y/256)); LCD_WR_DAT((u8)(Y%256)); LCD_WR_DAT(0x00); LCD_WR_DAT(0xA0);//定Y坐标
LCD_WR_CMD(0x2C);
}
/*================================================================================
** 作图函数子集
==================================================================================*/
/* 画彩色点函数. 调用参数: X列 Y行 color色 */
void Point(unsigned short X,unsigned short Y,unsigned char Fcolor)
{ MoveTo(X,Y);LCD_WR_DATA(COLOR); }
/* 画彩色水平线函数.调用参数: 起始点X列 Y行 w长度 Color色 */
void LineH(unsigned short X,unsigned short Y,unsigned short H,unsigned char Fcolor)
{ unsigned short n;
MoveTo(X,Y);
for(n=0;n<H;n++)LCD_WR_DATA(COLOR);
}
/* 画彩色垂直线函数.调用参数: 起始点X列 Y行 h长度 Color色 */
void LineV(unsigned short X,unsigned short Y,unsigned short V,unsigned char Fcolor)
{ unsigned short n;
for(n=0;n<V;n++){ MoveTo(X,Y+n); LCD_WR_DATA(COLOR); }
}
/* 任意两点画直线函数 调用参数:起始点X0列Y0行,结束点X1列Y1行,Color色 */
void Line(unsigned short X1,unsigned short Y1,unsigned short X2,unsigned short Y2,unsigned char Color)
{ unsigned short i;
float r;
if(X1==X2) /* 垂直线 */
{ if(Y1==Y2){ Point(X1,Y1,Color); return; /* 画点 */}
if(Y1<Y2)LineV(X1,Y1,Y2-Y1+1,Color);else LineV(X1,Y2,Y1-Y2+1,Color); return;
}
if(X1>X2){ i=X1;X1=X2;X2=i;i=Y1;Y1=Y2;Y2=i; } /* 交换坐标 */
if(Y1==Y2){ LineH(X1,Y1,X2-X1,Color);return; } /* 画水平线 */
r=(float)(Y2-Y1)/(float)(X2-X1); /* 计算斜率 */
if(r>=-1&&r<=1) /* 与水平夹角<=45度 */
for(i=0;i<(X2-X1);i++)Point(X1+i,Y1+i*r,Color); /* 画出斜线 */
else /* 斜率>1*/
{ r=1/r;
if(r>0) /* 与水平夹角>45度 */
for(i=0;i<(Y2-Y1);i++)Point(X1+i*r,Y1+i,Color); /* 画出斜线 */
else
{ r=-r;
for(i=0;i<(Y1-Y2);i++)Point(X1+i*r,Y1-i,Color); /* 画出斜线 */
}
}
}
/* 画彩色线方框程序 调用参数: 起始点X列 Y行,宽度w 高度h, 左上边色C1,右下边色C2,背景色BC(约定80为透明) */
void Box(unsigned short X,unsigned short Y,unsigned short H,unsigned short V,unsigned char C1,unsigned char C2,unsigned char BC)
{ short l;
LineH(X,Y,H,C1); LineV(X,Y,V,C1);
LineH(X,Y+V,H,C2); LineV(X+H,Y,V+1,C2);
if(BC!=80)//CLSA(X+1,Y+1,H-3,V,BC);
for(l=1;l<V;l++)LineH(X+1,Y+l,H-1,BC);
}
/*==================================================================================
** 在液晶显示屏显示5*7点阵ASC字符串函数(占用6*8点阵)
** 参数: 坐标 水平列X(0-127) 垂直行Y(0-159), * str串指针,Fcolor字前景色,Bcolor字背景色,约定:色号80为透明,Len指定长度
===================================================================================*/
void A8(unsigned short X,unsigned short Y, char *str,unsigned char Fcolor,unsigned char Bcolor,unsigned char Len)
{ unsigned char i,n,buf,A;
unsigned short j,l;
l=Len; //Strlen(str); /* 计算字符串字符数 */
for(j=0;j<l;j++) /* 串字符轮流处理*/
{ /* 逐个显示字符串 */
A=str-32; /* 取字符的ASC码 */
for(i=0;i<8;i++) /* 要写8行 */
{buf = ASC8; /* 取字模 */
MoveTo(X+j*6,Y+i); /* 定显示地址 */
for(n=0;n<6;n++) /* 横向显示6点*/
{ if((buf&0x80)==0x80)LCD_WR_DATA(COLOR); /* 字模点为1显示前景色 */
else /* 字模点为0显示原底色或背景色 */
{ if(Bcolor==80){ MoveTo(X+j*6+n,Y+i); } /* 透明显示模式:仅做地址+1定位 */
elseLCD_WR_DATA(COLOR); /* 正常显示模式:背景色 */
}
buf = buf << 1; /* 水平移位取点 */
} /* 水平6点显示毕*/
} /* 一个6*8点阵西文字符显示完毕 */
}/* 一字符串显示完毕 */
} /* A8() */
/*=================================================================================
** 在彩色LCD液晶显示屏显示16点阵字符串函数
** 参数: X列Y行坐标, * str串指针, Fcolor字前景色,Bcolor字背景色,约定:色号80为透明,Len指定长度
==================================================================================*/
void A12(unsigned short X,unsigned short Y, char *str,unsigned char Fcolor,unsigned char Bcolor,unsigned char Len)
{ /* 行Y(0-159) 列X(0-127) */
unsigned char i,buf,A,n;
unsigned short j,l;
A=0;A=0;
l=Len; //Strlen(str);
for(i=0;i<l;i++) /* 逐个显示字符串 */
{
A=str;A=str;
for(j=0;j<12;j++)
{ /* 写12行 */
buf = ASC12-32]; /* 取字模 */
MoveTo(X+i*8,Y+j); /* 字符左上角显示地址*/
for(n=0;n<8;n++) /* 西文字母横向显示8点 */
{ if((buf&0x80)==0x80)LCD_WR_DATA(COLOR); /* 字模点为1显示前景色 */
else /* 字模点为0显示原底色或背景色 */
{ if(Bcolor==80){ MoveTo(X+i*8+n,Y+j); } /* 透明显示模式: 仅地址+1定位 */
elseLCD_WR_DATA(COLOR); /* 正常显示模式:背景色 */
}
buf = buf << 1;
} /* 水平8点显示完毕 */
} /* 一个8*16点阵西文字符显示完毕 */
} /* for(i)*/
} /* A12()*/
/*===============================================================================
** 在彩色LCD液晶显示屏显示16点阵西文字符串函数(字模取自ROM)
** 参数: X列Y行坐标, * str串指针, Fcolor字前景色,Bcolor字背景色,约定:色号80为透明,Len指定长度
================================================================================*/
void A16(unsigned short X,unsigned short Y, char *str,unsigned char Fcolor,unsigned char Bcolor,unsigned char Len)
{ /* 行Y(0-159) 列X(0-127) */
char i,buf,A,n;
unsigned short j,l;
l=Len; //strlen(str);
for(i=0;i<l;i++) /* 逐个显示字符串 */
{A=str; /* 显示西文ASCII字符 */
for(j=0;j<16;j++)
{ /* 写16行 */
buf = ASC16; /* 取字模 */
MoveTo(X+i*8,Y+j); /* 字符左上角显示地址 */
for(n=0;n<8;n++) /* 西文字母横向显示8点 */
{ if((buf&0x80)==0x80)LCD_WR_DATA(COLOR); /* 字模点为1显示前景色 */
else /* 字模点为0显示原底色或背景色 */
{ if(Bcolor==80){ MoveTo(X+i*8+n,Y+j); } /* 透明显示模式: 仅地址+1定位 */
elseLCD_WR_DATA(COLOR); /* 正常显示模式:背景色 */
}
buf = buf << 1;
} /* 水平8点显示完毕 */
}/* 一个8*16点阵西文字符显示完毕 */
} /* while */
} /* P16() */
/*==================================================================================
** 在单色LCD液晶显示屏显示24*16点阵数字串函数
** 调用参数: X列Y行坐标, * str串指针, Fcolor字前景色,Bcolor字背景色,约定:色号80为透明,Len指定长度
====================================================================================*/
void A24(unsigned short X,unsigned short Y, char *str,unsigned char Fcolor,unsigned char Bcolor,unsigned char Len)
{/* X(0-127) Y(0-159) */
unsigned char n,C;
unsigned short i,j,L,Lw=0,ZM;
L=Len; //strlen(str);
for(j=0;j<L;j++)
{ C=str; /* 逐个显示字符串 */
for(i=0;i<24;i++)
{ /* 写24行 */
ZM=ASC24; /* 取字模码1 */
ZM=ZM*256+ASC24;/* 取字模码2 */
MoveTo(X+Lw,Y+i); /* 定位左上角 */
for(n=0;n<12;n++)
{ if((ZM&0x8000)==0x8000)LCD_WR_DATA(COLOR);/* 字模点为1显示前景色 */
else /* 字模点为0显示原底色或背景色 */
{ if(Bcolor==80) { MoveTo(X+Lw+n,Y+i); } /* 透明显示模式: 仅地址+1定位 */
else LCD_WR_DATA(COLOR); /* 正常显示模式:背景色 */
}
ZM = ZM << 1;
} /* 水平16点显示完毕 */
} Lw=Lw+12; /* 水平坐标位移 */
} /* 一位数字显示完毕*/
} /* A24() */
/*=========================================================================
** 在彩色LCD液晶显示屏显示16点阵中西文混合字符串函数(小字库字模取自ROM)
** 参数: X列Y行坐标, * str串指针, Fcolor字前景色,Bcolor字背景色,约定:背景色号80为透明
==========================================================================*/
void H16(unsigned short X,unsigned short Y, char *str,unsigned char Fcolor,unsigned char Bcolor)
{ /* 列X(0-127) 行Y(0-159) */
unsigned short i,j,l,m,n,p,HZM;
unsigned char ch,zm;
l=strlen(str); //求字符串长度
for(i=0;i<l;i++) //循环显示
{ ch=str;ch=str;
if(ch>160) //若是汉字...
{ m=1;p=0;
while(m!=0&&p<TotalHZ16) /* 查小字库汉字,若找到返m=0和指针p */
{ m=strncmp(ch,HZ16M,2); //比较...
if(m)p=p+1;
}
for(j=0;j<16;j++) /* 显示16行 */
{ HZM = HZ16; /* 取汉字模2字节 */
HZM = HZM*256+(unsigned char)(HZ16); //合成16位
MoveTo(X+i*8,Y+j); /* 起始显示点 */
for(n=0;n<16;n++) /* 汉字横向显示16点 */
{ if((HZM&0x8000)==0x8000)LCD_WR_DATA(COLOR); /* 字模点为1显示前景色 */
else /* 字模点为0显示原底色或背景色 */
{ if(Bcolor==80){ MoveTo(X+i*8+n,Y+j); } /* 透明显示模式: 仅地址+1定位 */
elseLCD_WR_DATA(COLOR); /* 正常显示模式:背景色 */
}
HZM=HZM<<1;/* 汉字点模左移出 */
} /* 水平16点显示完毕 */
} i++;
} /* 一个汉字显示完毕 */
else
{ for(j=0;j<16;j++)
{ /* 写16行 */
zm = ASC16-32];/* 取字模 */
MoveTo(X+i*8,Y+j); /* 字符左上角显示地址 */
for(n=0;n<8;n++) /* 西文字母横向显示8点 */
{ if((zm&0x80)==0x80)LCD_WR_DATA(COLOR); /* 字模点为1显示前景色 */
else /* 字模点为0显示原底色或背景色 */
{ if(Bcolor==80){ MoveTo(X+i*8+n,Y+j); } /* 透明显示模式: 仅地址+1定位 */
elseLCD_WR_DATA(COLOR); /* 正常显示模式:背景色 */
}
zm = zm << 1;
} /* 水平8点显示完毕 */
}/* 一个8*16点阵西文字符显示完毕 */
} /* else_if */
} // 循环显示str
} /* H16() */
/*======================================================================
** 在单色LCD液晶显示屏显示24点阵中西文混合字符串函数(小字库字模取自ROM)
** 调用参数: X列Y行坐标, * str串指针, Fcolor字前景色,Bcolor字背景色,约定:色号80为透明
=======================================================================*/
void H24(unsigned short X,unsigned short Y, char *str,unsigned char Fcolor,unsigned char Bcolor)
{ /* X(0-127) Y(0-159) */
unsigned char C;
unsigned short i,j,l,m,n,p,ZM;
unsigned long HZM;
l=strlen(str);
for(i=0;i<l;i++)
{ /* 逐个显示字符串 */
C=str;C=str; //取汉字内码
if(C>160) //是汉字...
{ m=1;p=0;
while(m!=0&&p<TotalHZ24) /* 搜索汉字,若找到返m=0和指针p */
{ m=strncmp(C,HZ24M,2);
if(m)p=p+1;
}
for(j=0;j<24;j++)
{ /* 循环写24行 */
HZM = HZ24; /* 取字模码 */
HZM = HZM*256+(unsigned char)(HZ24);
HZM = HZM*256+(unsigned char)(HZ24);//合成24位
MoveTo(X+i*12,Y+j); /* 字符左上角显示地址 */
for(n=0;n<24;n++) /* 汉字横向显示24点 */
{ if((HZM&0x800000)==0x800000)LCD_WR_DATA(COLOR); /* 字模点为1显示前景色 */
else /* 字模点为0显示原底色或背景色 */
{ if(Bcolor==80){ MoveTo(X+i*12+n,Y+j); } /* 透明显示模式:仅做地址+1定位 */
elseLCD_WR_DATA(COLOR); /* 正常显示模式:背景色 */
}
HZM = HZM << 1;
} /* 水平24点显示完毕 */
}
i++;
}
else
{ for(j=0;j<24;j++)
{ /* 写24行 */
ZM=ASC24-32]; /* 取字模码1 */
ZM=ZM*256+ASC24-32]; /* 取字模码2 */
MoveTo(X+i*12,Y+j); /* 定位左上角 */
for(n=0;n<12;n++)
{ if((ZM&0x8000)==0x8000)LCD_WR_DATA(COLOR);/* 字模点为1显示前景色 */
else /* 字模点为0显示原底色或背景色 */
{ if(Bcolor==80) { MoveTo(X+i*12+n,Y+j); } /* 透明显示模式: 仅地址+1定位 */
else LCD_WR_DATA(COLOR); /* 正常显示模式:背景色 */
}
ZM = ZM << 1;
} /* 水平12点显示完毕 */
} /* 一个12*24点阵字符显示完毕*/
} /* else_if */
}/* 循环逐个显示字符串 */
}/* H24() */
//=== END =============================================================
浦江一水
发表于 2023-11-6 20:26:49
本帖最后由 浦江一水 于 2023-11-6 20:28 编辑
有关ADC的头.H文件和.C实现文件
/*---------------------------------------------------------------------*/
// ADC.H
// STC32G12K128
// channel: 0--15
// ADC0 -- P1.0
// ADC1 -- P1.1
// ADC3 -- P1.3==> 实验通道
// ADC4 -- P1.4
// ADC5 -- P1.5
// ADC6 -- P1.6
// ADC7 -- P1.7
// ADC15: 基准电压1190mv ==> 实验通道
/*---------------------------------------------------------------------*/
#include "stdio.h"
#include "intrins.h"
#include "STC32G.h"
#ifndef _ADC_12B_H_
#define _ADC_12B_H_
/*************函数声明 **************/
void ADC_Init(void);
unsigned int Get_ADC12bitResult(unsigned char channel); //channel = 0~15
#endif
/***** END **************************************************************/
/*---------------------------------------------------------------------*/
// ADC.C 返回指定通道的ADC值
// STC32G12K128
// channel: 0--15
// ADC0 -- P1.0
// ADC1 -- P1.1
// ADC3 -- P1.3==> 实验通道
// ADC4 -- P1.4
// ADC5 -- P1.5
// ADC6 -- P1.6
// ADC7 -- P1.7
// ADC15: 基准电压1190mv ==> 实验通道
// 计算某通道的毫伏值算法: 两步法:
// 1: 读取基准通道15的ADC, 算出每一ADC字对应的毫伏值,Vad=1190/ADC
// 2: 读取指定通道XX的ADC, 算出指定通道的实际毫伏值, Vch=ADC*Vad
/*---------------------------------------------------------------------*/
#include "stdio.h"
#include "intrins.h"
#include "STC32G.h"
#include "ADC.h"
/************* 本地函数声明.H **************/
//void ADC_Init(void);
//u16Get_ADC12bitResult(u8 channel); //channel = 0~15
/********************* 初始化 *************************/
void ADC_Init(void)
{
ADCTIM = 0x3F; //设置 ADC 内部时序,ADC采样时间建议设最大值
ADCCFG = 0x2F; //设置 ADC 时钟为系统时钟/2/16
ADC_CONTR = 0x80; //使能 ADC 模块
}
//========================================================================
// 函数: u16 Get_ADC12bitResult(u8 channel)
// 描述: 查询法读一次ADC结果.
// 参数: channel: 选择要转换的ADC.
// 返回: 12位ADC结果.
// 版本: V1.0, 2012-10-22
//========================================================================
unsigned intGet_ADC12bitResult(unsigned char channel)//channel = 0~15
{
ADC_RES= 0; //返回值的高字节(寄存器)
ADC_RESL = 0; //返回值的低字节(寄存器)
ADC_CONTR = (ADC_CONTR & 0xf0) | channel; //设置ADC转换通道
ADC_START = 1;//启动ADC转换
_nop_(); _nop_(); _nop_(); _nop_();
while(ADC_FLAG == 0); //wait for ADC finish
ADC_FLAG = 0; //清除ADC结束标志
return(((unsigned int)ADC_RES << 8) | ADC_RESL);
}
/***** END ****************************************************************/
浦江一水
发表于 2023-11-6 20:33:04
本帖最后由 浦江一水 于 2023-11-7 09:39 编辑
有关本实验用到的两个键外设文件,KEY4_IO.H 和 KEY4_IO.C,与此前贴出的文件相同。见本贴 9#
有关本实验用到的ASCII字符模.H文件 , 与此前贴出的内容相同。见本贴 16#
有关本实验用到的汉字点阵模.H文件 , 如下: (注意汉字点阵取模的方式, 与中西文混合显示的输出的H16(...)和H24(...)函数算法有关)
//汉字小字库点阵模文件:LCD_HZK.H
//汉字取模: 横排→→
//24点阵汉字小字库索引列表...
const char HZ24M[]={
"单","片","机",
};
#define TotalHZ24 3 //说明一下24点阵小汉字库的字数
//24点阵汉字点阵模数组(排列顺序要与索引列表一致)
const char HZ24[]={
/* 单0 */{
0x04,0x00,0x80,0x03,0x00,0xE0,0x01,0x81,0x80,0x01,0xC3,0x00,0x00,0x86,0x00,0x0F,
0xFF,0xF0,0x0C,0x18,0x38,0x0C,0x18,0x30,0x0F,0xFF,0xF0,0x0C,0x18,0x30,0x0C,0x18,
0x30,0x0C,0x18,0x30,0x0F,0xFF,0xF0,0x0C,0x18,0x30,0x08,0x18,0x20,0x00,0x18,0x0C,
0x7F,0xFF,0xFE,0x00,0x18,0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00,
0x18,0x00,0x00,0x18,0x00,0x00,0x10,0x00,},
/* 片1 */{
0x00,0x04,0x00,0x00,0x07,0x00,0x04,0x06,0x00,0x07,0x06,0x00,0x06,0x06,0x00,0x06,
0x06,0x00,0x06,0x06,0x08,0x06,0x06,0x1C,0x07,0xFF,0xFE,0x06,0x00,0x00,0x06,0x00,
0x00,0x06,0x00,0x00,0x06,0x03,0x00,0x07,0xFF,0x80,0x06,0x03,0x00,0x06,0x03,0x00,
0x06,0x03,0x00,0x0C,0x03,0x00,0x0C,0x03,0x00,0x18,0x03,0x00,0x10,0x03,0x00,0x20,
0x03,0x00,0x40,0x03,0x00,0x00,0x02,0x00,},
/* 机2 */{
0x04,0x00,0x00,0x07,0x08,0x60,0x06,0x0F,0xF0,0x06,0x0C,0x60,0x06,0x0C,0x60,0x06,
0x0C,0x60,0x06,0xCC,0x60,0x7F,0xEC,0x60,0x0E,0x0C,0x60,0x0E,0x0C,0x60,0x1F,0x0C,
0x60,0x16,0xCC,0x60,0x16,0x6C,0x60,0x36,0x4C,0x60,0x26,0x0C,0x60,0x46,0x0C,0x60,
0x86,0x0C,0x62,0x06,0x18,0x62,0x06,0x18,0x62,0x06,0x30,0x63,0x06,0x20,0x7F,0x06,
0x40,0x3E,0x06,0x80,0x00,0x04,0x00,0x00,},
};
//16点阵汉字小字库索引列表...
const char HZ16M[]={
"单","片","机",
};
#define TotalHZ16 3 //说明一下16点阵小汉字库的字数
//16点阵汉字点阵模数组(排列顺序要与索引列表一致)
const char HZ16[]={
/* 单0 */{
0x10,0x10,0x08,0x20,0x04,0x48,0x3F,0xFC,0x21,0x08,0x21,0x08,0x3F,0xF8,0x21,0x08,
0x21,0x08,0x3F,0xF8,0x21,0x00,0x01,0x04,0xFF,0xFE,0x01,0x00,0x01,0x00,0x01,0x00,},
/* 片1 */{
0x00,0x40,0x10,0x40,0x10,0x40,0x10,0x44,0x1F,0xFE,0x10,0x00,0x10,0x00,0x10,0x00,
0x1F,0xF0,0x10,0x10,0x10,0x10,0x10,0x10,0x20,0x10,0x20,0x10,0x40,0x10,0x80,0x10,},
/* 机2 */{
0x10,0x00,0x10,0x10,0x11,0xF8,0x11,0x10,0xFD,0x10,0x11,0x10,0x31,0x10,0x39,0x10,
0x55,0x10,0x51,0x10,0x91,0x10,0x11,0x10,0x11,0x12,0x12,0x12,0x14,0x0E,0x18,0x00,},
};
神农鼎
发表于 2023-11-6 21:43:59
楼主的贴,将来应该转移到 TFT 版块去,给大家抛砖引玉{:4_196:}
浦江一水
发表于 2023-11-12 20:59:36
关于STC32G12K128实验板驱动TM1638数码管模块的实验
坛子里有布丁橘长的“视频教程-STC32位8051-屠龙刀-第0-100期合集”, 深受大家的欢迎喜爱,让人得益菲浅。
对多种模块给出了实验教程。附件文档中给出了各种模块的清单XLS。
其中有一款TM1638的模块,令我产生兴趣。
但是好像没有看到布丁橘长有关这款模块的实验介绍。
顺着布丁橘长的连接指引,淘购了一块来做实验。。。。
仅用三个IO口,就能实现对8个按键、8个LED发光管、8位LED数码管的操作控制,如此节省IO资源, 在单片机应用项目中是有非常现实意义的。
百度文档中有人谈到了对这模块的应用感受, 说是“又爱又恨”, 爱的是功能多、效率高,恨的是芯片数据手册的描述太简单而模糊,弄得人看不懂,导致实验很不顺利。
比如芯片数据手册中这样描述:
你能看得出,如果要在第三位显示一个“0”, 地址是哪个吗?
没有参考代码,只好自己摸索实验了。。。
于是我将实验板与TM1638模块连接起来。如图所示:
经过一番曲曲折折的调试摸索实验,终于弄懂或猜出了数据手册描述的意思。实现了对TM1638模块的控制使用。
实验结果如图:
在这个实验中实现:
1. 在8位数码管上定位显示整数或小数及字符串显示;
2. 按S1键增加显示亮度; 按S2键减小显示亮度;
3. 显示键值, 图中"C80"的"80"就是键值的16进制显示, 对应键:S1=01,S2=02,S3=04,S4=08, S5=10,S6=20,S7=40,S8=80;
4. 设一个无符号字节变量(0...255)变化,按S3键使这变量加一 ,按S4键使这变量减一, 显示此变量值(如图中以16进制显示"3F")。
同时上面8个LED发光管对应变量的8位显示变化: 从左到右, 低位到高位。如图中显示变量为“3F”, 2进制即00111111,那么发光管显示○○○○○○●●(○为1,●为0)