基于STC8G芯片的时钟显示系统
基于STC8G芯片的时钟显示系统
这里写目录标题
- 基于STC8G芯片的时钟显示系统
- 一、电路原理图设计
- 1.1EDA__立创EDA
- 1.1.1 主要器件BOM--仅供参考
- 1.1.2主要电路原理图设计
- ①电源原理图
- ② 数码管原理图
- ③ STC8G原理图
- ④ 下载口原理图
- ⑤ 按键原理图
- ⑥ 无线通信模块原理图
- ⑥ 辅助模块原理图
- ⑥ 外设模块原理图
- 1.2 PCB
- 1.2.1顶层
- 1.2.2底层
- 1.2.3 2D
- 1.2.4 3D
- 二、程序设计
- 2.1 主函数程序
- 2.2 系统初始化程序
- 2.3 串口驱动程序
- 2.4 看门狗驱动程序
- 2.5 掉电记忆程序
- 2.6 时钟、定时器驱动程序
- 2.7 定时器跑秒程序
- 2.8 MAX7129驱动程序
- 2.9 MAX7129显示程序
- 2.10 无线通信模块程序
- 总结
一、电路原理图设计
1.1EDA__立创EDA
1.1.1 主要器件BOM–仅供参考
ID | Name | Footprint | Supplier | Price |
---|---|---|---|---|
1 | STC8G2K64S4 | LQFP-32 | C915671 | ¥8 |
2 | 11.0592MHZ | HC-49US | C358645 | ¥0.7869 |
3 | LED | LED-SMD | C375449 | ¥0.1071 |
4 | KEY | KEY-TH_4P | C2762975 | ¥0.6092 |
5 | AMS1117-3.3 | SOT-223 | C6186 | ¥0.9204 |
6 | 电容C | 0603 | ||
7 | 电阻R | 0603 | ||
8 | MAX7129 | 网络购买 | 数码管 | ¥3.42 |
9 | DHT11 | 网络购买 | 温湿度 | ¥4.00 |
10 | OLED 0.91 | 网络购买 | OLED | ¥7.40 |
11 | HC05 | 网络购买 | 蓝牙 | ¥18 |
12 | BC95 | 网络购买 | NB | ¥89 |
13 | DC电源插头插座 | 网络购买 | 电源 | ¥0.4 |
1.1.2主要电路原理图设计
①电源原理图
U8—DC直流电源插头插座: 用于5V适配器供电;
网络购买封装自己添加
U4–AMS1117-3.3 :用于5V转3.3V;
② 数码管原理图
U10/U3—MAX7129: 用于显示数字;
网络购买封装自己添加
实物参考
两个MAX7129电路设计为串联
③ STC8G原理图
STC8G主芯片网络标号连接
④ 下载口原理图
串口 1引出:用于下载
下载驱动
⑤ 按键原理图
⑥ 无线通信模块原理图
无线通信模块–兼容两种无线通信
NB模块-BC-95
4G模块-WH-LTE-7S1
封装自己按照尺寸画的;
WH-LTE-7S1介绍
WH-LTE-7S1_hareware_V1.0.2文档获取以下信息
①供电----DC5-16V
②串口通信----TTL
③模块复位----RESET
(2)串口调试助手测试
测试工具
查看USR-Cat-1_AT_ V1.0.5文档
按照AT指令的标准进行“问”与“答”
⑥ 辅助模块原理图
电源指示灯 --用于电源指示
程序状态灯 --用于程先生状态显示
晶振电路 --用于时钟系统
复位电路 --用于复位
⑥ 外设模块原理图
串口3 ----用于蓝牙模块透传
DHT11 ----用于温湿度获取
OLED ----用于数据显示
1.2 PCB
1.2.1顶层
1.2.2底层
1.2.3 2D
1.2.4 3D
二、程序设计
2.1 主函数程序
// 主逻辑函数 默认上电日期2023-03-17- 08:00:00系统自加时间;系统记忆亮度等级为5;
struct ctm {char issync;char isleap;char tm_year; /* years since 1900 */char tm_mon; /* months since January, 0 to 11 */char tm_mday; /* day of the month, 1 to 31 */char tm_hour; /* hours since midnight, 0 to 23 */char tm_min; /* minutes after the hour, 0 to 59 */char tm_sec; /* seconds after the minute, 0 to 60*/
};
struct ctm c_lct;#define JAN_2014_1970 0x52c35a80 /* 3187296000 2001 - 1900 in seconds */
//初始化时间
void Init_value(void)
{t_utc=JAN_2014_1970;//计算日期(设备上电请求时间)必须大于等于2003年,否则NTP计算将会溢出(long类型)c_lct.tm_sec=0;c_lct.tm_min=0;c_lct.tm_hour=08;c_lct.tm_mday=17;c_lct.tm_mon=03;c_lct.tm_year=23; /* years since 2000 */
}
// 主程序 ---------------------
void main()
{Init_value();Init_MSP(); ReadCfg(); EA_On(); //使能总中断Init_Cat();SendSyncEn=P21;SetWriteFlag(0);while (1){Wdt_fresh(); //清看门狗,否则系统复位Task_WDT(); //清外部看门狗813,否则系统复位Task_Max7219(TASKS_LED);
#if defined(CAT) Task_Cat(TASKS_CAT);
#elif defined(NB)Task_Cat(TASKS_NB);
#endif }
}
2.2 系统初始化程序
// 系统初始化函数初始化时钟初始化IO初始化串口初始化看门狗初始化定时器0 初始化定时器2
void IO_Init(void)
{P0M1 = 0;P0M0 = 0; //设置为准双向口,M1M0:00=准双向口,01=推挽,10=高阻,11=开漏P1M1 = 0;P1M0 = 0; //设置为准双向口,M1M0:00=准双向口,01=推挽,10=高阻,11=开漏P2M1 = 0;P2M0 = 0; //设置为准双向口,M1M0:00=准双向口,01=推挽,10=高阻,11=开漏P3M1 = 0;P3M0 = 0; //设置为准双向口,M1M0:00=准双向口,01=推挽,10=高阻,11=开漏P1M0 |= 0x10; //设置P14为推挽输出 P2M0 |= 0x0E; //设置P21,P22,P23为推挽输出
}
void EA_On(void)
{EA = 1; //使能总中断
}void Init_MSP(void)
{SystemClock_Config(); //初始化时钟IO_Init();Wdt_Config(); //初始化看门狗TM0_Init(3); //初始化定时器0,频率200HZ,优先级3。TM2_Baud_Init(); //初始化定时器2做串口1,2,3,4通用波特率发生器,优先级固定为最低优先级0#ifdef USE_UART1 UART1_Init(0,UART1_BPR); //初始化串口1
#endif
#ifdef USE_UART2 UART2_Init(); //初始化串口2
#endif
#ifdef USE_UART3 UART3_Init(1, UART3_BPR); //初始化串口3
#endif
#ifdef USE_UART4 UART4_Init(1, UART4_BPR); //初始化串口4,
#endif }
2.3 串口驱动程序
// 串口1/2/3/4驱动函数
#ifdef USE_UART1
void UART1_Init(unsigned char mode, unsigned int baud) //串口1、2可设优先级,串口3、4固定为最低优先级0,mode=0,使用默认定时器波特率
{SCON = 0x50; //串口1控制寄存器SCON(可位访问)选用串口方式1(可变8位,0x40) ,允许串口接收数据(0x10)PCON &= (~(SMOD | SMOD0)); //电源管理寄存器PCON(不可位访问),串口1波特率不加倍,无帧错检测功能AUXR &= (~(UART_M0x6 | S1ST2)); //辅助寄存器1 AUXR(不可位访问),串口1方式0波特率不加6倍,定时器1做串口1波特率发生器if(mode > 0) //定时器1做串口1波特率发生器 //串口1可用定时器2和定时器1做波特率发生器{TMOD &= 0x0f; //定时器0/1模式寄存器TMOD(不可位访问),定时器1,模式0(16位自动重载模式)AUXR |= T1x12; //辅助寄存器1 AUXR(不可位访问),定时器1以系统不分频INTCLKO &= (~T1CLKO); //中断与时钟输出控制寄存器INTCLKO(不可位访问),关闭定时器1时钟输出TH1 = (-SYSCLK / baud / 4) >> 8;TL1 = (-SYSCLK / baud / 4); //65536-11059200/115200/4=0FFE8HTR1 = 1; //定时器0/1、外部中断0/1控制寄存器TCON(可位访问),启动定时器1}else{AUXR |= S1ST2; //辅助寄存器1 AUXR(不可位访问),定时器2做串口1波特率发生器}ES = 1; //中断使能寄存器IE(可位访问) 使能串口1中断
}
void send_uart1( unsigned char *_ucaBuf, int _usLen)
{if(_usLen>0){tx_num1=_usLen;tx_cnt1=1;pMsg1= _ucaBuf;SBUF = *pMsg1++;}
}
int get_uart1( unsigned char *_ucaBuf)
{int temp = 0; if(rx_t1>=UOUT_TIME){if(rx_cnt1>0){memcpy (_ucaBuf, rxBuf1, rx_cnt1);temp=rx_cnt1;rx_cnt1=0;//重新开始接收,接收完置位,表明停止接收了}} return temp;
}#endif#ifdef USE_UART2
void UART2_Init(void)//串口1、2可设优先级,串口3、4固定为最低优先级0,mode=0,使用默认定时2器波特率
{//串口2只能用定时器2作为波特率发生器S2CON = S2REN; //串口2控制寄存器S2CON(不可位访问),选用串口方式0(可变8位) ,允许串口接收数据(0x10) ,IE2 |= ES2; //中断使能寄存器2 IE2(不可位访问)使能串口2中断
}
void send_uart2( unsigned char *_ucaBuf, int _usLen)
{if(_usLen>0){tx_num2=_usLen;tx_cnt2=1;pMsg2=(unsigned char xdata *)_ucaBuf;S2BUF = *pMsg2++;}
}
int get_uart2( unsigned char *_ucaBuf)
{int temp = 0; if(rx_t2>=UOUT_TIME){if(rx_cnt2>0){memcpy (_ucaBuf, rxBuf2, rx_cnt2);temp=rx_cnt2;rx_cnt2=0;//重新开始接收,接收完置位,表明停止接收了}} return temp;
}
#endif#ifdef USE_UART3
void UART3_Init(unsigned char mode, unsigned int baud) //串口1、2可设优先级,串口3、4固定为最低优先级0,mode=0,使用默认定时器2波特率
{if(mode > 0) //定时器3做串口3波特率发生器 //串口3可用定时器2和定时器3做波特率发生器{S3CON = S3ST3 | S3REN; //串口3控制寄存器S3CON(不可位访问)串口方式0(可变8位),允许串口接收数据(0x10) ,选用定时器3作为波特率发生器//TM3PS //定时器3的8位预分频寄存器(TM3PS),默认为0 定时器2时钟=系统时钟SYSCLK/(TM3PS+1)T3H = (-SYSCLK / baud / 4) >> 8;T3L = (-SYSCLK / baud / 4); //65536-11059200/115200/4=0FFE8HT4T3M &= 0xf0;T4T3M |= (T3R | T3x12); //启动定时器3,定时器以系统不分频}else//定时器2做串口3波特率发生器,注意与其它串口参数的影响{S3CON = S3REN; //串口3控制寄存器S3CON(不可位访问)串口方式0(可变8位),允许串口接收数据(0x10) ,默认选用定时器2作为波特率发生器}IE2 |= ES3; //中断使能寄存器2 IE2(不可位访问)使能串口3中断
}
void send_uart3( unsigned char *_ucaBuf, int _usLen)
{if(_usLen>0 ) {tx_num3=_usLen;tx_cnt3=1;pMsg3=(unsigned char xdata *)_ucaBuf;S3BUF = *pMsg3++;}#endif#ifdef USE_UART4
void UART4_Init(unsigned char mode, unsigned int baud) //串口1、2可设优先级,串口3、4固定为最低优先级0,mode=0,使用默认定时器2波特率
{if(mode > 0) //定时器4做串口4波特率发生器 //串口4可用定时器2和定时器4做波特率发生器{S4CON = S4ST4 | S4REN; //串口4控制寄存器S4CON(不可位访问)串口方式0(可变8位),允许串口接收数据(0x10) ,选用定时器4作为波特率发生器//TM4PS //定时器4的8位预分频寄存器(TM4PS),默认为0 定时器2时钟=系统时钟SYSCLK/(TM4PS+1)T4H = (-SYSCLK / baud / 4) >> 8;T4L = (-SYSCLK / baud / 4); //65536-11059200/115200/4=0FFE8HT4T3M &= 0x0f;T4T3M |= (T4R | T4x12); //启动定时器4,定时器以系统不分频}else//定时器2做串口4波特率发生器,注意与其它串口参数的影响{S4CON = S4REN; //串口4控制寄存器S4CON(不可位访问)串口方式0(可变8位),允许串口接收数据(0x10) ,默认选用定时器2作为波特率发生器}IE2 |= ES4; //中断使能寄存器2 IE2(不可位访问)使能串口4中断
}
void send_uart4( unsigned char *_ucaBuf, int _usLen)
{if(_usLen>0) {tx_num4=_usLen;tx_cnt4=1;pMsg4=(unsigned char xdata *)_ucaBuf;S4BUF = *pMsg4++;}
}
int get_uart4( unsigned char *_ucaBuf)
{int temp = 0; if(rx_t4>=UOUT_TIME){if(rx_cnt4>0){memcpy (_ucaBuf, rxBuf4, rx_cnt4);temp=rx_cnt4;rx_cnt4=0;//重新开始接收,接收完置位,表明停止接收了}}return temp;
}
unsigned char get_uart4_tx_idle(void)
{if(tx_cnt4==tx_num4)return 1;else return 0;
}
void set_uart4_tx_clr(void)
{tx_num4=0;tx_cnt4=0;
}
#endif
2.4 看门狗驱动程序
// 看门狗驱动函数看门狗喂狗函数
void Wdt_Config(void)
{WDT_CONTR = 0x27; //使能看门狗,溢出时间约为8s
}
void Wdt_fresh(void)
{WDT_CONTR |= CLR_WDT; //清看门狗,否则系统复位
}
void delay_ms(int t)
{static int lms=0;int mt=t;while(mt>0){if(lms!=mscnt)//5ms一次{lms=mscnt;mt-=MS_TICK;}Wdt_fresh(); //清看门狗,否则系统复位Task_WDT(); //清外部看门狗813,否则系统复位}}
2.5 掉电记忆程序
// 掉电记忆写函数掉电记忆读函数
void IapIdle()
{IAP_CONTR = 0; //关闭IAP功能IAP_CMD = 0; //清除命令寄存器IAP_TRIG = 0; //清除触发寄存器IAP_ADDRH = 0x80; //将地址设置到非IAP区域IAP_ADDRL = 0;
}unsigned char IapRead(unsigned int addr)
{unsigned char dat;IAP_CONTR = 0x80; //使能IAPIAP_TPS = 12; //设置擦除等待参数12MHZIAP_CMD = 1; //设置IAP读命令IAP_ADDRL = addr; //设置IAP低地址IAP_ADDRH = addr >> 8; //设置IAP高地址IAP_TRIG = 0x5a; //写触发命令(0x5a)IAP_TRIG = 0xa5; //写触发命令(0xa5)_nop_();dat = IAP_DATA; //读IAP数据IapIdle(); //关闭IAP功能return dat;
}void IapProgram(unsigned int addr, unsigned char dat)
{IAP_CONTR = 0x80; //使能IAPIAP_TPS = 12; //设置擦除等待参数12MHZIAP_CMD = 2; //设置IAP写命令IAP_ADDRL = addr; //设置IAP低地址IAP_ADDRH = addr >> 8; //设置IAP高地址IAP_DATA = dat; //写IAP数据IAP_TRIG = 0x5a; //写触发命令(0x5a)IAP_TRIG = 0xa5; //写触发命令(0xa5)_nop_();IapIdle(); //关闭IAP功能
}void IapErase(unsigned int addr)
{IAP_CONTR = 0x80; //使能IAPIAP_TPS = 12; //设置擦除等待参数12MHZIAP_CMD = 3; //设置IAP擦除命令IAP_ADDRL = addr; //设置IAP低地址IAP_ADDRH = addr >> 8; //设置IAP高地址IAP_TRIG = 0x5a; //写触发命令(0x5a)IAP_TRIG = 0xa5; //写触发命令(0xa5)_nop_(); //IapIdle(); //关闭IAP功能
}
void WirteCfg(void)
{IapErase(0x00);//擦除从0开始的一个扇区,512个字节 IapProgram(0x01, CfgData[1]);//写入亮度IapProgram(0x02, CfgData[2]);//写入通讯时长高IapProgram(0x03, CfgData[3]);//写入通讯时长低CfgData[4]=(CfgData[1]+CfgData[2]+CfgData[3])&0xff;IapProgram(0x04, CfgData[4]);//写入校验IapProgram(0x00, 0xa5);//写入标识
}
#define UPDATE_INTERVAL 0xFF
void ReadCfg(void)
{unsigned char i=0;CfgData[0]=IapRead(0x00); //标识 0xa5if(CfgData[0]==0xa5){for (i=1;i<91;i++){ //读多个数据CfgData[i]=IapRead(i); }}//使用默认参数CfgData[1]=0x05; //亮度CfgData[2]=UPDATE_INTERVAL>>8;CfgData[3]=UPDATE_INTERVAL&0xff;//校时周期
}
2.6 时钟、定时器驱动程序
// 时钟底层驱动函数定时器0底层驱动函数定时器2底层驱动函数
// 底层配置程序 ---------------------------------------------------------------------------------------------------------------
void SystemClock_Config(void)
{P_SW2 = 0x80;XOSCCR = 0xc0; //启动外部晶振while (!(XOSCCR & 1)); //等待时钟稳定CLKDIV = 0x00; //时钟不分频CKSEL = 0x01; //选择外部晶振P_SW2 = 0x00;
}
void TM2_Baud_Init(void)//定时器2做串口1,2,3,4通用波特率发生器,优先级固定为最低优先级0
{//固定定时器2做串口1,2,3,4通用波特率发生器,优先级固定为最低优先级0AUXR &= (~(T2R | T2x12));AUXR |= (T2R | T2x12); //启动定时器2,定时器2以系统不分频,定时器2做串口1波特率发生器INTCLKO &= (~T2CLKO); //中断与时钟输出控制寄存器INTCLKO(不可位访问),关闭定时器2时钟输出//TM2PS //定时器2的8位预分频寄存器(TM2PS),默认为0 定时器2时钟=系统时钟SYSCLK/(TM2PS+1)T2H = (-SYSCLK / UART2_BPR / 4) >> 8;T2L = (-SYSCLK / UART2_BPR / 4); //65536-11059200/115200/4=0FFE8H}
void TM0_Init(unsigned char pri) //定时器0、1可设优先级,定时器2、3、4固定为最低优先级0,最高为3
{//定时器0 初始化 系统时钟12分频,模式0自动重载的16位定时器TMOD &= 0xf0; //定时器0/1模式寄存器TMOD(不可位访问),定时器0,模式0(16位自动重载模式)AUXR &= (~T0x12); //辅助寄存器1 AUXR(不可位访问),定时器0系统12分频AUXR |=T0x12; //辅助寄存器1 AUXR(不可位访问),定时器0系统不分频INTCLKO &= (~T0CLKO); //中断与时钟输出控制寄存器INTCLKO(不可位访问),关闭定时器0时钟输出TH0 = 0x28; //11.0592M/200hz=55296;//65536-55296 =10240(0x2800)TL0 = 0x02;PT0 = pri & 0x01; //定时器中断优先级PT0H,PT0:PT0=1 11=3 最高优先级IPH &= (~PT0H); //无法按位操作IPH |= (pri & PT0H); //PT0H=1TR0 = 1; //定时器0/1、外部中断0/1控制寄存器TCON(可位访问),启动定时器0 不能修改TH0和TH1的值,会改变定时器周期ET0 = 1; //中断使能寄存器IE(可位访问) 使能定时器0中断
}
2.7 定时器跑秒程序
// 定时器跑秒函数获取秒函数获取毫秒函数获取微秒函数
#define MS_TICK 5 //最大间隔5ms(200HZ),否则需调整12分频,避免溢出
#define cpu_on() P26=0
#define cpu_off() P26=1
static volatile unsigned long idata t_utc;//从1970年开始的时间秒数
static volatile unsigned int idata mscnt=0;//使用volatile,不优化,每次都更新寄存器值void Time_Update(void)
{systimer+=MS_TICK; //= SYSTEMTICK_PERIOD_MS;
}
// 中断回调程序 -------------------------
void Time_Update_Callback(void)
{mscnt+=MS_TICK;if(mscnt>=1000) //跑秒{mscnt=0; t_utc++;cpu_on();}else if(mscnt>=500) //使能读QCCLK{cpu_off();}Time_Update();
}unsigned long GetUtcTime(void)//获取绝对标准UTC时间的总秒数,从1970开始
{return t_utc;
}
unsigned long GetMsTime(void)//获取当前毫秒数
{return mscnt;
}
unsigned long GetUsTime(void)//获取当前微秒数
{unsigned long xdata t;t=TH0;t<<=8;t+=TL0; t=65536-t;//读取定时器值t=(t*5000)/4608;//11.0592M/200hz/12=4608;//65536-4608 =60928(0xee00)t+= ((unsigned long)mscnt*1000);return t;
}
2.8 MAX7129驱动程序
// 数码管驱动函数
//------------------------------------------------------------------------------------
//-- DESCRIPTION : BIN to seven segments converter
//-- segment encoding
//-- e
//-- +---+
//-- f | | d
//-- +---+ <- g
//-- a | | c
//-- +---+
//-- b
//-- Outputs (data_out) active : high
//-- .,a,b,c,d,e,f,g -->(bit7~bit0)
//------------------------------------------------------------------------------------//------------------------------------------------------------------------------------
//-- DESCRIPTION : BIN to seven segments converter HS210801K-16
//-- segment encoding
//-- a
//-- +---+
//-- f | | b
//-- +---+ <- g
//-- e | | c
//-- +---+
//-- d
//-- Outputs (data_out) active : low
//-- .,g,f,e,d,c,b,a -->(bit7~bit0)
//------------------------------------------------------------------
//-- Outputs (data_out) active : high MAX7219 共阴,高有效
//-- .,a,b,c,d,e,f,g -->(bit7~bit0)
//----------------------------------------------------------------------------------
//MAX7219 --VCC GND CLK CS DATA 对应SZZ40-SFM-NB1.0
#define CLK_Hi() P21 = 1 //高,CLK上升沿数据被移入内部移位寄存器,下降沿从DOUT移出 一次称一位
#define CLK_Lo() P21 = 0 //低,CLK下降沿数据从DOUT移出 一次称一位
#define CS_Hi() P22 = 1 //高,CS上升沿锁存以上移位进输入的最后16位数据 MAX7219为LOAD MAX7221为CS,只有在CS为低选通时,CLK输入才有效
#define CS_Lo() P22 = 0 //低,CS置低选通 MAX7219,串行数据载入移位寄存器 MAX7219为LOAD MAX7221为CS,只有在CS为低选通时,CLK输入才有效
#define DIN_Hi() P23 = 1 //高,DIN,数据位输入高
#define DIN_Lo() P23 = 0 //低,DIN,数据位输入低#define Delay() _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
/*定义MAX7219寄存器 ******************************************************************/
#define REG_NO_OP 0x00 // 定义空操作 register
#define DIG_1 0x01 // 定义数码管1 register
#define DIG_2 0x02 // 定义数码管2 register
#define DIG_3 0x03 // 定义数码管3 register
#define DIG_4 0x04 // 定义数码管4 register
#define DIG_5 0x05 // 定义数码管5 register
#define DIG_6 0x06 // 定义数码管6 register
#define DIG_7 0x07 // 定义数码管7 register
#define DIG_8 0x08 // 定义数码管8 register
#define REG_DECODE 0x09 // 定义解码控制 register
#define REG_INTENSITY 0x0a // 定义显示亮度 register
#define REG_SCAN_LIMIT 0x0b // 定义扫描限制 register
max7219共阴极 对应显示段表 ([0], [1], [2], [3], [4], [5], [6], [7], [8], [9], [A], [b], [C], [d], [E], [F], blank) ***********************************************************/
unsigned char code code_table[17]= {0x7e,0x30,0x6d,0x79,0x33,0x5b,0x5f,0x70,0x7f,0x7b,0x77,0x1f,0x4e,0x3d,0x4f,0x47,0x00}; /*采用数组*/
/****************************************************************** * MAX7219_Send()描述: 向MAX7219传送一字节数据
Arguments : dataout = data to send
Returns : none ******************************************************************/
void send (unsigned char datain)
{unsigned char i,temp; for (i=8; i>0; i--) { CLK_Lo(); // CLK 置低 temp=datain&0x80;if (temp==0x80) // 判断并输出一位 DIN_Hi(); // 输出"1" else // 或 DIN_Lo(); // 输出"0" datain<<=1; //datain左移位,以便再次与0x80按位与CLK_Hi(); // CLK 置高 }
}/**************************************************************** * MAX7219_Write()/MAX7219_Write_1()描述: 向 MAX7219 写命令
Arguments : reg_number = register to write to
dataout = data to write to MAX7219
Returns : none ************************************************************** */
void MAX7219_Write (unsigned char add1, unsigned char dat1) //向第一片MAX7219写数据
{ CS_Lo(); // CS置低选通 MAX7219send(add1); // 写register number 到 MAX7219 send(dat1); // 写 data 到 MAX7219 CS_Hi(); // 利用CS上升沿锁存以上移位进输入的16位数据
}
void MAX7219_Write_12 (unsigned char add1, unsigned char dat1,unsigned char add2, unsigned char dat2) //向两片MAX7219写数据
{ CS_Lo(); // CS置低选通 MAX7219send(add2); // 写register number 到 第一片MAX7219 send(dat2); // 写 data 到 第一片MAX7219 send(add1); // 写register number 到 第一片MAX7219 send(dat1); // 写 data 到 第一片MAX7219 CS_Hi(); // 利用CS上升沿锁存以上移位进输入的16位数据
}
/******************************************************************** MAX7219_DisplayChar()描述: 使某一位显示一个数字
Arguments : digit = digit number (0-7)
character = character to display (0-9, A-Z)
dp = dp to display (0, 0x80)
Returns : none ****************************************************************/
void MAX7219_DisplayChar (unsigned char digit,unsigned char character,unsigned char dp)
{ MAX7219_Write((digit+1), code_table[character&0x0f]|dp);
}
//PS:这个函数可以不要,直接调用写数据函数就可以了(原版)
/******************************************************************** MAX7219_Clear()/MAX7219_clear_1()描述: 清除所有位的显示
Arguments : none
Returns : none *****************************************************************/
void MAX7219_Clear (void)
{ unsigned char i; for (i=0; i < 8; i++)MAX7219_Write(i, 0x00); // 清除第一片MAX7219所有位的显示
}
/********************************************************************
MAX7219_SetBrightness()描述: 设置数码管显示亮度
Arguments : brightness (0-15)
Returns : none *****************************************************************/
void MAX7219_SetBrightness (unsigned char brightness)
{ brightness &= 0x0f; // 屏蔽高位字节 MAX7219_Write(REG_INTENSITY, brightness); // 设置数码管显示亮度
}
/******************************************************************** MAX7219_DisplayTestStop()描述: 退出 test 模式
Arguments : none
Returns : none ***************************************************************/
void MAX7219_DisplayTestStop (void)
{ MAX7219_Write(REG_DISPLAY_TEST, 0); //置 MAX7219为正常显示模式
}
/********************************************************************
MAX7219_ShutdownStop()描述: 退出 shutdown 模式
Arguments : none
Returns : none ****************************************************************/
void MAX7219_ShutdownStop (void)
{ MAX7219_Write(REG_SHUTDOWN, 1); //置MAX7219为正常显示模式
}
/******************************************************************** MAX7219_Init() 描述: MAX7219初始化模块,应该先于其他MAX7219函数而被调用
Arguments : none
Returns : none *****************************************************************/
void Max7219_Reset (void)
{ //设置为全显示0~7 DIG 减小扫描位数,增加扫描率,亮度功率增加,显示小于3位时,要设置ISET电阻来限制最大电流,避免单个DIG电流过大。MAX7219_Write(REG_SCAN_LIMIT, 7);MAX7219_Write(REG_DECODE, 0x00); //所有位设置为非解码方式 MAX7219_ShutdownStop(); //置MAX7219为(非关断)正常显示模式 MAX7219_DisplayTestStop(); //置MAX7219为(非test)正常显示模式 MAX7219_SetBrightness((CfgData[1]*3)&0x0f); //设置数码管显示亮度
}
2.9 MAX7129显示程序
// 数码管显示函数
void MAX7219_ClearChar (void)
{ unsigned int i=0;for(i=0;i<8;i++){MAX7219_Write(i+1,CODE_BLANK);}
}
/******************************************************************** MAX7219_DisplayTestStart()描述: 进入 test 模式
Arguments : none
Returns : none ****************************************************************/
void MAX7219_DisplayTestStart (void)
{ MAX7219_Write(REG_DISPLAY_TEST, 1); //置MAX7219为 test 模式
}
void MAX7219_DisplayTime (struct ctm t)
{ //根据显示实际调整第一个参数的数值MAX7219_DisplayChar(8,2,0);MAX7219_DisplayChar(9,0,0);MAX7219_DisplayChar(10,(t.tm_year%100)/10,0);MAX7219_DisplayChar(11,t.tm_year %10,0);MAX7219_DisplayChar(12,(t.tm_mon+1)/10,0);MAX7219_DisplayChar(13,(t.tm_mon+1) %10,0);MAX7219_DisplayChar(14,t.tm_mday/10,0);MAX7219_DisplayChar(15,t.tm_mday %10,0);MAX7219_DisplayChar(0,t.tm_hour/10,0);MAX7219_DisplayChar(1,t.tm_hour %10,0x80);MAX7219_DisplayChar(2,t.tm_min/10,0);MAX7219_DisplayChar(3,t.tm_min %10,0x80);MAX7219_DisplayChar(4,t.tm_sec/10,0);MAX7219_DisplayChar(5,t.tm_sec %10,0);
}
#define TASKS_HOLD 100
void Task_Max7219(unsigned int tk)
{ static unsigned char index=0;static unsigned long xdata lt = 0;unsigned long xdata ut = 0; ut = GetMsTime(); //一毫秒一次循环if(ut >= tk && ut < (tk + TASKS_HOLD)) //按ms的时序开始,tk 为0则立即更新{ut = GetUtcTime();//一秒一次循环if(ut != lt) //每秒更新一次{lt = ut; switch (index){case 0:Max7219_Reset();MAX7219_DisplayTestStart();break;case 1:case 2:break;case 3:MAX7219_DisplayTestStop(); //置MAX7219为正常显示模式 MAX7219_Clear(); //清除所有位的显示 MAX7219_DisplayVer();break;default:MAX7219_DisplayTime(c_lct);}if(index<100)index++;}}
}
2.10 无线通信模块程序
// 函数
#define GET get_uart2
#define PUT send_uart2//有人WH-LTE-7S1-------------------------------
unsigned char code ATE0[] = "usr.cn#AT+E=OFF\r\n";
unsigned char code AT_CSQ[] = "usr.cn#AT+CSQ\r\n";
unsigned char code AT_IMEI[] = "usr.cn#AT+IMEI?\r\n";
unsigned char code AT_ICCID[] = "usr.cn#AT+ICCID?\r\n";
unsigned char code AT_LBS[] = "usr.cn#AT+LBS?\r\n";
unsigned char code AT_LBS2[] = "usr.cn#AT+LBS=2\r\n";
unsigned char code AT_CCLK[] = "usr.cn#AT+CCLK?\r\n";
unsigned char code AT_SOCKA_R[] = "usr.cn#AT+SOCKA?\r\n";
unsigned char code AT_SOCKA_W[] = "usr.cn#AT+SOCKA=";
unsigned char code CFG_SOCKA[] = "UDP,ntp.(获取时间网站).net,123\r\n";
unsigned char code AT_SOCKAEN_R[] = "usr.cn#AT+SOCKAEN?\r\n";
unsigned char code AT_SOCKAEN_W[] = "usr.cn#AT+SOCKAEN=ON\r\n";
unsigned char code AT_SHORTATM_W[] = "usr.cn#AT+SHORTATM=120\r\n";
unsigned char code AT_SOCKB_R[] = "usr.cn#AT+SOCKB?\r\n";
unsigned char code AT_SOCKB_W[] = "usr.cn#AT+SOCKB=";
unsigned char code CFG_SOCKB[] = "UDP,iot.(获取时间网站).net,端口号\r\n";
unsigned char code AT_SOCKBEN_R[] = "usr.cn#AT+SOCKBEN?\r\n";
unsigned char code AT_SOCKBEN_W[] = "usr.cn#AT+SOCKBEN=ON\r\n";
unsigned char code AT_SHORTBTM_W[] = "usr.cn#AT+SHORTBTM=120\r\n";
unsigned char code AT_HEARTEN_R[] = "usr.cn#AT+HEARTEN?\r\n";
unsigned char code AT_HEARTEN_W[] = "usr.cn#AT+HEARTEN=OFF\r\n";
unsigned char code AT_STMSG_R[] = "usr.cn#AT+STMSG?\r\n";
unsigned char code AT_STMSG_W[] = "usr.cn#AT+STMSG=chijiu_iot21_001\r\n";
unsigned char code AT_CACHEN_R[] = "usr.cn#AT+CACHEN?\r\n";
unsigned char code AT_CACHEN_W[] = "usr.cn#AT+CACHEN=OFF\r\n";
unsigned char code AT_SDPEN_R[] = "usr.cn#AT+SDPEN?\r\n";
unsigned char code AT_SDPEN_W[] = "usr.cn#AT+SDPEN=ON\r\n";
unsigned char code AT_S[] = "usr.cn#AT+S\r\n";
static int p_write(unsigned char* buf, int len)//用于统一发送数据格式,其中buf不能是ptx发送缓存
{ if(len>0){memset(ptx, 0, TX_LEN);//清空发送缓存memcpy (ptx, buf, len);//通一发送数据类型和指针类型PUT(ptx,len);}return len;
}static int p_read(unsigned char* buf)
{int idata len=0;len=GET(buf);return len;
}
static void get_sdpen(void)
{p_write((unsigned char*)AT_SDPEN_R,strlen(AT_SDPEN_R));
}
static void get_sig(void)
{p_write((unsigned char*)AT_CSQ,strlen(AT_CSQ));
}
static void get_imei(void)
{p_write((unsigned char*)AT_IMEI,strlen(AT_IMEI));
}
static void get_iccid(void)
{p_write((unsigned char*)AT_ICCID,strlen(AT_ICCID));
}
static void get_lbs(void)
{p_write((unsigned char*)AT_LBS,strlen(AT_LBS));
}
static void get_lbs2(void)
{p_write((unsigned char*)AT_LBS2,strlen(AT_LBS2));
}
static void cat_config(void)
{int len0,len1=0;p_write((unsigned char*)ATE0,strlen(ATE0));//关回显delay_ms(100);memset(ptx, 0, TX_LEN);//清空发送缓存len0=strlen(AT_SOCKA_W);memcpy (ptx, (unsigned char*)AT_SOCKA_W, len0);//通一发送数据类型和指针类型len1=strlen(CFG_SOCKA);memcpy (ptx+len0, (unsigned char*)CFG_SOCKA, len1);//通一发送数据类型和指针类型PUT(ptx,len0+len1);delay_ms(100);p_write((unsigned char*)AT_SOCKAEN_W,strlen(AT_SOCKAEN_W));//设置SOCKA启用delay_ms(100);p_write((unsigned char*)AT_SHORTATM_W,strlen(AT_SHORTATM_W));//设置SOCKA短链接时长delay_ms(100);memset(ptx, 0, TX_LEN);//清空发送缓存len0=strlen(AT_SOCKB_W);memcpy (ptx, (unsigned char*)AT_SOCKB_W, len0);//通一发送数据类型和指针类型len1=strlen(CFG_SOCKB);memcpy (ptx+len0, (unsigned char*)CFG_SOCKB, len1);//通一发送数据类型和指针类型PUT(ptx,len0+len1);delay_ms(100);p_write((unsigned char*)AT_SOCKBEN_W,strlen(AT_SOCKBEN_W));//设置SOCKB启用delay_ms(100);p_write((unsigned char*)AT_SHORTBTM_W,strlen(AT_SHORTBTM_W));//设置SOCKB短链接时长delay_ms(100);p_write((unsigned char*)AT_HEARTEN_W,strlen(AT_HEARTEN_W));//设置心跳关闭delay_ms(100);p_write((unsigned char*)AT_CACHEN_W,strlen(AT_CACHEN_W));//设置串口缓存关闭delay_ms(100); p_write((unsigned char*)AT_SDPEN_W,strlen(AT_SDPEN_W));//设置套节字分发开启delay_ms(100); p_write((unsigned char*)AT_S,strlen(AT_S));}static void socka( char* buf)
{char *q;char *p;q=buf;//p=strstr(q,"SOCKA:UDP,ntp.zhonglianwang.net,123\r\n");//设置SOCKA地址 //如果修改,上边设置参数判读时也必须修改p=strstr(q,CFG_SOCKA);if(p==NULL){initialized=2;//复位重置}
}
static void sockb( char* buf)
{char *q;char *p;q=buf;p=strstr(q,CFG_SOCKB);if(p==NULL){initialized=2;//复位重置}
}static void sockaen( char* buf)
{char *q;char *p;q=buf;p=strstr(q,"SOCKAEN:OFF\r\n");//设置SOCKA启用if(p!=NULL){initialized=2;//复位重置}
}
static void sockben( char* buf)
{char *q;char *p;q=buf;p=strstr(q,"SOCKBEN:OFF\r\n");//设置SOCKB启用if(p!=NULL){initialized=2;//复位重置}
}
static void hearten( char* buf)
{char *q;char *p;q=buf;p=strstr(q,"HEARTEN:ON\r\n");//设置心跳关闭if(p!=NULL){initialized=2;//复位重置}
}
static void cachen( char* buf)
{char *q;char *p;q=buf;p=strstr(q,"CACHEN:ON\r\n");//设置串口缓存关闭if(p!=NULL){initialized=2;//复位重置}
}
static void sdpen( char* buf)
{char *q;char *p;q=buf;p=strstr(q,"SDPEN:ON\r\n");if(p!=NULL){if(initialized!=2){initialized=1;//初始化成功 ltdl=0; }}else{p=strstr(q,"SDPEN:OFF\r\n");//设置套节字分发开启if(p!=NULL){initialized=2;//复位重置}}
}void socket_send(unsigned char *buf,unsigned int len,unsigned char ch)//0~3
{//套接字协议
}void socket_receive(unsigned char *buf,unsigned int len)//0~3
{//套接字协议
}static void rec_pro(unsigned char* buf,int len)
{char *q;q=strstr((char*)buf,"+CSQ:");//\r\n+CSQ: 31, 99\r\n\r\nOK\r\nif(q!=NULL)csq(q);//+CSQ: 31, 99\r\n\r\nOK\r\n// q=strstr((char*)buf,"+CCLK:");//\r\n+CCLK: “20/06/19,20:05:19+32”\r\n\r\nOK\r\n
// if(q!=NULL)cclk(q);q=strstr((char*)buf,"chijiu");//\r\n+IMEI:864333040712457\r\n\r\nOK\r\nif(q!=NULL)chijiu(q);q=strstr((char*)buf,"+ICCID:");//\r\n+ICCID:89860621240067311755\r\n\r\nOK\r\nif(q!=NULL)iccid(q); q=strstr((char*)buf,"+IMEI:");//\r\n+IMEI:864333040712457\r\n\r\nOK\r\nif(q!=NULL)imei(q);q=strstr((char*)buf,"+LBS:");//\r\n+LBS: LNG = 114.43350220, LAT = 30.49159431, TIME = 2020-12-11 15:45:39, ADDINFO: 武汉市高新大道426号\r\n\r\nOK\r\nif(q!=NULL)lbs(q);q=strstr((char*)buf,"+SOCKA:");//\r\n+SOCKA:<TCP,UDP>,<1~100 bytes>,<1~65535>if(q!=NULL)socka(q);q=strstr((char*)buf,"+SOCKAEN:");//\r\n+SOCKAEN:ON\r\n\r\nOK\r\nif(q!=NULL)sockaen(q);q=strstr((char*)buf,"+SOCKB:");//\r\n+SOCKB:<TCP,UDP>,<1~100 bytes>,<1~65535>if(q!=NULL)sockb(q);q=strstr((char*)buf,"+SOCKBEN:");//\r\n+SOCKBEN:ON\r\n\r\nOK\r\nif(q!=NULL)sockben(q); q=strstr((char*)buf,"+HEARTEN:");//\r\n+HEARTEN:OFF\r\n\r\nOK\r\nif(q!=NULL)hearten(q); q=strstr((char*)buf,"+CACHEN:");//\r\n+CACHEN:OFF\r\n\r\nOK\r\nif(q!=NULL)cachen(q); q=strstr((char*)buf,"+SDPEN:");//\r\n+SDPEN:ON\r\n\r\nOK\r\nif(q!=NULL)sdpen(q);socket_receive(buf,len);
}#define cat1_on() P14=1
#define cat1_off() P14=0
void Init_Cat(void)
{cat1_on();
}
void Task_Cat(unsigned int tk)
{ static unsigned long idata lt = 0;static unsigned char idata lm = 0;unsigned long idata ut = 0;unsigned int idata usCRC=0;int idata len=0;len=p_read(prx);if(len>0){rec_pro(prx,len);if(cmd_en==1){cmd_en=0;ut=clk_packet(upBuf);第一个客体包(1时间)ut=clk_packet_add(upBuf,ut,prx,len,18);//ADDRsocket_send(upBuf,ut,1);}}ut = GetMsTime();if(ut >= (tk + dl_index) && ut < (tk + TASKS_HOLD + dl_index)) //按ms的时序开始,tk 为0则立即更新,{ut = GetUtcTime();if(ut != lt) //每秒更新一次{lt = ut;//执行TASK---------------------------if(ltdl<(((unsigned int)CfgData[2]<<8)|CfgData[3]))ltdl++;else {ltdl=0;if(lm<48)lm++;//每(48*校时周期)后,上传输一次地理信息else lm=0;}if(initialized==2 || initialized==0){if((ltdl&0x1f)==0x10)get_imei();else if((ltdl&0x1f)==0x11)p_write((unsigned char*)AT_STMSG_R,strlen(AT_STMSG_R));//查询启动信息else if((ltdl&0x1f)==0x12)p_write((unsigned char*)AT_SOCKA_R,strlen(AT_SOCKA_R));//查询SOCKA地址else if((ltdl&0x1f)==0x13)p_write((unsigned char*)AT_SOCKAEN_R,strlen(AT_SOCKAEN_R));//查询SOCKA启用else if((ltdl&0x1f)==0x14)p_write((unsigned char*)AT_SOCKB_R,strlen(AT_SOCKB_R));//查询SOCKB地址else if((ltdl&0x1f)==0x15)p_write((unsigned char*)AT_SOCKBEN_R,strlen(AT_SOCKBEN_R));//查询SOCKB启用else if((ltdl&0x1f)==0x16)p_write((unsigned char*)AT_HEARTEN_R,strlen(AT_HEARTEN_R));//查询心跳关闭else if((ltdl&0x1f)==0x17)p_write((unsigned char*)AT_CACHEN_R,strlen(AT_CACHEN_R));//查询串口缓存关闭else if((ltdl&0x1f)==0x18)get_iccid();else if((ltdl&0x1f)==0x19)get_sdpen();//查询套节字分发开启else if((ltdl&0x1f)==0x1a){if(initialized==2){initialized=0; //0:未初始化,1:初始化成功,2;复位重置,3;校時成功cat_config();ltdl=0;}}}else{ut=GetNtpSync();//数据上传时刻----if((ltdl&0xffff)==0x12)get_lbs();else if((ltdl&0xffff)==0x13)get_sig(); //一天1M数据,一分钟不超694字节(往返),32秒一次上传数据(数据最好不超过108字节)(20+8+77),64秒一次NTP(20ip头+8UDP头+48数据=76,76*2=152字节)else if((ltdl&0xffff)==0x2C)//UPDATA{len=clk_packet(upBuf);第一个客体包(1时间) len=clk_packet_add(upBuf,len,prx,5,16);//客体16--子钟--驱动(状态) socket_send(upBuf,len,1);if(GetSyncOK()==0x01){if(initialized==1){ltdl=dl_index;//初始化校时成功后,根据IMEI号差开时序initialized=3;}}}else if((ltdl&0xff)==0x00)//NTP 同步周期固定为48~256秒//数据NTP同步时刻-首次链接,延时大------{if(GetSyncOK()!=1){ //第一次NTP同步本地时间后将ntp_en一直为1ntp_en=0;}else{ntp_en=1;}construct_packet(upBuf);//数据包长48socket_send(upBuf,48,0);}else if((ltdl&0xff)==0x07 || (ut!=0x01 && (ltdl&0x07)==0x07) && (ltdl&0xff)<=SYNCPRE_MIN)//NTP 同步周期固定为48~256秒 次数大于NTP的SYNC_MAX{ntp_en=1;construct_packet(upBuf);//数据包长48socket_send(upBuf,48,0);check_clk();}else if((ltdl&0xffff)==0x0011){if(lm==2)get_lbs2();//数据获取地理位置时刻--}}}}}
总结
上述程序中并未完全给出,但是思路没问题。
基于STC8G芯片的时钟显示系统相关推荐
- 超大计算机屏幕台历时钟,大屏幕日历时钟显示-系统.pdf
( ) 天津纺织工学院学报 第16卷第4期 1997 . 16 . 4 ( 1997) JOU RNAL O F T IAN J IN IN ST ITU T E O F V o l N o . 55 ...
- 个人项目——基于STM32的智能教务显示系统
这个项目也是我给别人代做的,大家先看一下视频,了解一下这个项目 点击观看视频 客户要求基本是这样的:现在大学的教室门口不都贴着课程表嘛,然后每个学期都要换,上面有这个学期要上的课,每一个格子里有课程名 ...
- 基于ISD1760的语音时钟播报系统
系统功能: 时间.温度.湿度等信息的实时显示,并语音可播报,具备闹钟功能. 可与PC上位机连接(串口),记录采集数据并绘制数据曲线. 配合语音软件,可作为语音芯片录音板(开发板)用,为您节省购买拷贝机 ...
- 单片机c语言编程 时钟加日历转换,基于52单片机电子时钟日历系统的设计
该系统是以52单片机为基础,以时钟日历芯片DSl2887为核心构建的时钟系统.完成的功能如下:显示年.月.日.星期.小时.分钟.秒钟,具有1OO年的日历,具有掉电不丢失性,能够通过按键调整时间.DS1 ...
- 基于FPGA的数字时钟显示(万年历lcd1602)
一. lcd1602a的驱动和配置 (1) lcd1602a的管脚分配图,在程序中,我们需要对相应的管脚进行操作,才能使其正确显示 (2) 由于我使用的板子EP4CE6上的晶振是50MHZ,而lc ...
- 基于图像处理的水果自助售卖系统(自助水果售卖机)
目录 第一章 概述 1.1 发展概要 1.2 国内外研究现状 1.3 研究目的和意义 1.4 方案介绍 第二章 软件设计方案 2.1 整体程序框架 2.2 opencv识别水果算法 2.2.1算法整体 ...
- 基于51单片机1602温度显示时钟
基于51单片机LCD1602温度显示时钟 要在1602上显示时间和温度先要了解1602是如何显示的.详情可以参考我之前的文章基于51单片机1602显示 :时间显示可以用时钟芯片DS1302,但是此次我 ...
- 毕业设计 —— 基于STM32手势控制显示系统的设计
目录 一.前言 二.项目背景及资源分享 三.项目简介 1.项目名称 2.系统框架 3.功能简介 4.控制核心 5.最小系统: 6.外围模块: 四.相关设计原理及框图 1.系统设计的原理 2.手势识别原 ...
- 基于51单片机的时钟系统
这一次带来的项目是课程设计级别的基于51单片机的时钟系统,本次的项目共有两种,一种是基础功能时钟,上电后自动从00-00-00开始计时,另一种加上了调时功能,上电后自动从00-00-00开始,当需要 ...
最新文章
- hive向表格中插入数据并分析语句
- Linux imooc learning
- Docker的简单介绍与安装(Windows10)
- ASP.NET页面事件详解
- python matplotlib绘图大全(散点图、柱状图、饼图、极坐标图、热量图、三维图以及热图)...
- sql 注射_令人惊讶的注射
- Python使用正则表达式检查书稿中不应该出现的重复字
- Unitest框架的使用(四)HTMLTestRunner输出测试报告
- 常见MIME类型例表
- 自然语言领域中图神经网络模型(GNN)应用现状(论文)
- 惠普打印机换硒鼓(墨盒)
- 三维扫描仪中投射模块/投影仪推荐
- sim900发送文件到服务器,sim900与云服务器的连接
- 开会总结【1】ADL129
- 前端开发JS--匀速运动
- 【基础】dB、dBm、dBc等概念的解释
- 行业实战 | 5G+边缘计算+“自由视角” 让体育赛事更畅快
- 横井军平(WIKI资源收集)
- 关于Python的基础练习题
- QGIS入门实验十四 半透明立体影像图
热门文章
- npm yarn pnpm
- LIS3DH 加速度值 读取处理
- 怎么把http图片改成背景图HTML,web前端:将图片设置成页面的背景-网页页面设置...
- 防范保险企业内部风险,原点安全出席中国寿险财险科技应用高峰论坛
- carlife和android auto,了解下Apple Carplay与Android Auto吧,未来买车可能就看它了
- 差分定位中控软件_无人机中的RTK差分定位技术解析,不懂得来科普吧
- 关于联想收购 IBM 的 PC 部门。
- MySQL 计算百分比
- python十进制转二进制循环,python十进制转二进制的详解
- c语言计算器取百分数,简易计算器的代码--------我终于可以编40行以上的代码了...