- 打卡等级:以坛为家II
- 打卡总天数:493
- 最近打卡:2025-05-01 08:31:58
荣誉版主
- 积分
- 3476
|
初试 8051U, 做个小实验...
首先感谢国芯论坛官方赠送寄来 8051U 新芯片,
使本单片机爱好者有机会接触和得到学习实验的机会。
STC8051U其中封装之一的PDIP40芯片,
其引脚分布对比传统的8031以及89C51,除了几个特殊引脚以外,
全部对应相同。
这就使人立即想到是否可以利用传统51单片机实验板来做实验了。
手头正好有一块QX-MCS51_V3.0实验板, 换上STC8051U以后, 果然, 无需做任何硬件改动, 就能上手实验了。
或许这可称是STC8051U的亮点和特别用心了,老项目可以很方便地直接升级提高性能了。
本人做了一个最基本的、简单的实验,内容涵盖:
1,对LED灯驱动;
2,对LCD1602点阵字符显示屏的驱动;
3,实验四个独立按键功能,能分别辨识长按和短按;
(当按下底部四个键之一时,LCD屏幕和LED灯显示键值)
4,串口通讯实验,与上位PC机对话,实现串口屏功能。
(PC机发送串口屏指令时,LCD执行显示,发送非串口屏指令时,原字符串返回PC机)
由于QX-MCS51_V3.0实验板,有USB转TTL接口,并具有自动断电上电功能,
因此,在使用STC-ISP软件时,顺利对接,检测MCU类型,制作串口仿真芯片等等,都顺利通过。
( 有关ADC、DMA、SPI、I2C、PWM...等外设功能, 有待逐步学习实验.... )
主程序贴一下:
/******************************************************************
* 工程: Test STC8051U(DIP40) + LCD1602A
* 基于: QX-MCS51_V3.0(STC89C52)单片机实验板
* 实验: LCD1602串口显示屏,8位数据控制,USART1_串口通讯,4键8值..
* 四键: P30/P31/P32/P33 8LED:P10...P17
* 说明: 测试STC8051U在传统51实验板上,不做任何硬件改动的实验...
* 编程: 浦晓明(浦江一水) 2024-07-12 ...
*******************************************************************/
#include "STC8051U.h"
#include <stdio.h>
#include <string.h>
#include "KEY4_IO.H" //4键盘相关函数
#include "LCD1602.H" //LCD1602A显示屏相关函数
//波特率计算...
#define FOSC 11059200UL //晶振频率
#define BRT (256 - FOSC / 9600 / 32) //按照波特率9600计算
//#define BRT (256 - FOSC / 115200 / 32) //按照波特率115200计算
sbit LED0 = P1^7; //运行状态指示
char RxBuf[24],k; //串口接收缓存
unsigned short RxCount=0; //接收计数器
char S[20]; //LCD显示缓存
unsigned char X,Y; //坐标
unsigned char RxOK=0; //串口通信接收到标志
//毫秒级延时
void delay(unsigned int ms)
{ unsigned int x,y;
for(x = ms; x > 0; x--)
for(y =114; y > 0; y--);
}
//串口初始化:
void UART_init()
{
SCON= 0x50;
TMOD= 0x20; //T1工作模式2 8位自动重装
TH1 = BRT; //0xFD;
TL1 = BRT; //0xFD; //比特率115200
TR1 = 1; //启动T1定时器
AUXR= 0x40;
SM0 = 0;
SM1 = 1; //串口工作方式1 10位异步
REN = 1; //串口允许接收
ES = 1; //串口中断打开
EA = 1; //开总中断
}
/*----------------------------
通过串口1发送单字节数据
----------------------------*/
void SendData(unsigned char ch)
{
SBUF = ch; //写数据到UART数据寄存器
while(TI == 0);
TI = 0;
}
/*----------------------------
通过串口1发送字符串
----------------------------*/
void SendString(char *s)
{
while (*s) //检测字符串结束标志
{ SendData(*s++); } //发送当前字符
}
//--------------------------------------------------------------
// 串口1接收中断服务...
//--------------------------------------------------------------
void UART() interrupt 4
{ unsigned char ch=0;
if(RI) //检测是否接收完成
{ ch=SBUF; //接收单字节
RI = 0; //清除标志位
if(ch==0x0A) //结尾标志
{ RxOK=1; //接收到指令串置接收到标志
if((RxCount>0)&&(RxBuf[RxCount-1]==0x0D)){ RxBuf[RxCount-1]=0;RxBuf[RxCount]=0; }
}
else if(RxCount<19)RxBuf[RxCount++]=ch;
}
}
//--------------------------------------------------------------
// 主程序入口
//--------------------------------------------------------------
void main(void)
{ unsigned char i,mode;
unsigned int wait=0;
//IO端口初始化
WTST = 0; //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
//IO端口初始化//全部为准双向口
P0M1 = 0x00; P0M0 = 0x00; //设置为准双向口
P1M1 = 0x00; P1M0 = 0x00; //设置为准双向口
P2M1 = 0x00; P2M0 = 0x00; //设置为准双向口
P3M1 = 0x00; P3M0 = 0x00; //设置为准双向口
P4M1 = 0x00; P4M0 = 0x00; //设置为准双向口
//外设初始化
UART_init();
LCD_Init(); //初始化LCD1602
LCD_CLS(); //测试清屏函数
LCD_Blink(0); //测试函数
LCD_Cursor(0); //测试函数
LCD_SetXY(0,0);//测试函数
delay(5);
LED0 = 0; delay(1000); //测试IO口控制 LED0亮
LED0 = 1; delay(1000); //测试IO口控制 LED0灭
//显示屏初始界面
LCD_STR(0,0,"STC8051U_U1_9600");
LCD_STR(1,0,"LCD1602A+4KEY=00");
//测试通讯口发送字符串
SendString("STC8051U_UART1_OK\r\n");
delay(1000);
//大循环
while(1)
{ k=0;
k=RDKEY(); //扫描按键
if(k!=0)
{ sprintf(S,"KEY=%02X ",(unsigned int)k); //当有键按下时, 显示键值,(<1秒为短按 >=1秒为长按)
LCD_STR(1,10,S); //比如: 短按Key1,显示=10, 长按显示=11...
P1 = ~k; //显示键值
}
//运行指示灯...
if(wait==0) { LED0 = 0; } // LED亮
if(wait==200){ LED0 = 1; RxOK=0;RxCount=0;RxBuf[0]=0; } // LED灭
wait=wait<2250?wait+1:0; //计数器循环
//串口屏通讯处理....
if(RxOK) //接收到指令串
{ //解析串口接收指令字符串,显示之
switch(RxBuf[0])
{ case 'P': //显示指令
X=RxBuf[1]-0x30;
Y=RxBuf[2]-0x30; if(Y>9)Y=Y-7;
for(i=0;i<RxCount-3;i++){ S=RxBuf[3+i]; S[i+1]=0; }
LCD_STR(X,Y,S); //显示接收字符串
break;
case '@': X=RxBuf[1]-0x30;
Y=RxBuf[2]-0x30; if(Y>9)Y=Y-7;
LCD_SetXY(X,Y); //光标定位
break;
case '_': mode=RxBuf[1]-0x30;if(mode>0)mode=1;
LCD_Cursor(mode);//光标显示
break;
case '*': mode=RxBuf[1]-0x30;if(mode>0)mode=1;
LCD_Blink(mode); //光标闪动
break;
case 'C': mode=RxBuf[1]-0x30;
if(mode==0)LCD_STR(0,0," ");//清屏第一行
if(mode==1)LCD_STR(1,0," ");//清屏第二行
if(mode>=2)LCD_CLS(); //清全屏
break;
default: RxBuf[RxCount]=0; SendString(RxBuf); SendData(0x0D); SendData(0x0A); break; //默认返回原串...
}
for(i=0;i<24;i++)RxBuf=0;RxOK=0; RxCount=0;
} //清除接收缓存
delay(10);
}
}
//******************************************************************************
// 附件: LCD1602串口屏通信控制指令协议,9600,8,1,N
//----------------------------------------------------------------------
// 共五条指令, 说明如下...
//----------------------------------------------------------------------
// 1, 格式: PXYsss...\r\n +0D+0A
// 其中: P -- 命令字 指定坐标显示字符串;
// X -- 显示行坐标, X=0或1,表示第一行或第二行
// Y -- 显示列坐标, Y=0...F(超过9用ABCDEF的16进制表示)
// sss... 需要显示的字符串 (长度限于16字符)(LCD1602每行最多显示16字符)
// \r\n 发送串结尾标志,回车换行符 即+0x0D+0x0A,(以下同)
// 实例: P00ABCDEFG+0.1234(\r\n) 在显示屏第一行首显示"ABCDEFG+0.1234"
//----------------------------------------------------------------------
// 2, 格式: Cm\r\n
// 其中: C -- 命令字 清屏
// m -- 参数 0:清第一行 1:清第二行 2:清全屏
// 实例: C0\r\n 显示屏第一行被清空;
//----------------------------------------------------------------------
// 3, 格式: @XY\r\n
// 其中: @ -- 命令字 指定当前光标坐标
// X,Y -- 参数 X:行 Y:列
// 实例: @01\r\n 当前光标在第一行第1列 (光标是否显示取决于以下指令)
//----------------------------------------------------------------------
// 4, 格式: *m\r\n
// 其中: * -- 命令字 光标闪烁显示
// m -- 参数 0:不闪烁 1:闪烁
// 实例: *1 在先前指定的坐标位置闪烁光标;
//----------------------------------------------------------------------
// 5, 格式: _m\r\n
// 其中: _ -- 命令字 底画线显示
// m -- 参数 0:不显示底画线 1:显示底画线
// 实例: _1 在先前指定的坐标位置显示底画线; (底画线显示后,光标闪烁取消)
//*******************************************************************************
其余见工程文件所包含, 供有兴趣的初学爱好者们参考:
03 TestSTC8051U.rar
(38.44 KB, 下载次数: 195)
|
2
喜欢他/她就送朵鲜花吧,赠人玫瑰,手有余香!
-
+2
楼主威武~
-
+1
楼主威武~
|