STC8H试验箱学习记录
89C51熟悉一遍了,开始学习8H 先上试验箱图片,感谢STC。 本帖最后由 lezjin 于 2024-5-12 16:01 编辑#include "../STC8H.h"
#include "delay.h"
void main(void)
{
unsigned char i;
P6M0 = 0x00; P6M1 = 0x00;
P4M0 = 0x00; P4M1 = 0x00;
P40 = 0;
while(1)
{
for(i = 0; i<8; i++)
{
P6 = ~(0x01 << i);
delay_ms(200);
}
}
先来个流水灯,成功点亮,查看官方例子,用的是数组查表的方法,感觉查表的方法应该比这个运算要快一些。不过点灯的话就无所谓了。
第二,定时器
ISP生成的定时器代码中没有开中断,开启EA后不能运行,查看手册和官方例子,ET0没有打开,打开后正常运行。
void Timer0_Init(void) //1毫秒@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xCD; //设置定时初始值
TH0 = 0xD4; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
#include "../STC8H.h"
#include "stc8h_timer.h"
unsigned int count;
void main(void)
{
P6M0 = 0x00; P6M1 = 0x00;
P4M0 = 0x00; P4M1 = 0x00;
P40 = 0;
Timer0_Init();
ET0 = 1;
EA = 1;
while (1)
{
if(count >= 1000) //1毫秒@11.0592MHz1000 次为一秒
{
count = 0;
P67 = ~P67;
}
}
}
void Time0_ISR() interrupt TMR0_VECTOR//定时器0中断函数
{
count++;
}
三,数码管
官方的例子数码管编码取反和位选那里(7-位置)不好理解,容易混淆,既然查表了,还要取反再做其他运算,和流水灯的查表就违背了, 这样流水灯还不如用循环。
找了个数码管的原理图,重新编码了一下,显示函数逻辑就清晰了。
#include "../STC8H.h"
#include "stc8h_timer.h"
//共阳数码管编码0-16,最后一个位熄灭状态, 高位 dp g f e d c b a 低位
unsigned char code display_array[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,
0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff};
unsigned char code display_we[]={0x7F, 0xbf, 0xdf, 0xef,0xf7, 0xfb, 0xfd, 0xfe}; //位码
typedef struct
{
unsigned char hour; //时
unsigned char minute; //分
unsigned char second; //秒
}Timetype_t;
Timetype_t Time_count = {23, 59, 57};
unsigned int g_scanflag; //刷新时间标志位
unsigned char g_display_index; //显示位索引
unsigned char Ledbuff; //显示缓存
bit g_bms;//1毫秒标志
void displayrtc(void)
{
if(Time_count.hour >= 10)
{
Ledbuff =Time_count.hour / 10;
}
else
Ledbuff = 16;//编码数组最后一个,熄灭状态,0xFF
Ledbuff = Time_count.hour % 10;
Ledbuff = Time_count.minute / 10;
Ledbuff = Time_count.minute % 10;
Ledbuff = Time_count.second / 10;
Ledbuff = Time_count.second % 10;
}
void rtc (void)
{
if (++Time_count.second >= 60)
{
Time_count.second = 0;
if (++Time_count.minute >= 60)
{
Time_count.minute = 0;
if (++Time_count.hour >= 24)
{
Time_count.hour = 0;
}
}
}
}
void displayscan(void)
{
P7 = display_we;
P6 = display_array];
g_display_index++;
g_display_index %= 6;
}
void main(void)
{
P6M1 = 0xff; P6M0 = 0xff; //设置为漏极开路(实验箱加了上拉电阻到3.3V)
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
Timer0_Init();
ET0 = 1;
EA = 1;
rtc();
displayrtc();
while (1)
{
if(g_bms)
{
g_bms = 0;
if(++g_scanflag >= 1000) //1秒刷新一次时间
{
g_scanflag = 0;
rtc();
displayrtc();
}
}
}
}
void Time0_ISR(void) interrupt TMR0_VECTOR//定时器0中断函数
{
displayscan();
g_bms = 1 ;
}
可以跑时间了 四。T0做外部计数器
我只配置了T0,T1同理就没有配置,试的过程中发现 P3.4,P3.5 不使能内部4.1k上拉电阻,也能用,当然还是参考手册,设置为上拉4.1K电阻。
同时注意到初始值都设置为0xff,试了下我把低位改成0XFe,测试现象按两次才会才会进入一次中断。
#include "../STC8H.h"
void main(void)
{
P0M0 = 0x00; P0M1 = 0x00;
P1M0 = 0x00; P1M1 = 0x00;
P2M0 = 0x00; P2M1 = 0x00;
P3M0 = 0x00; P3M1 = 0x00;
P4M0 = 0x00; P4M1 = 0x00;
P5M0 = 0x00; P5M1 = 0x00;
P6M0 = 0x00; P6M1 = 0x00;
P7M0 = 0x00; P7M1 = 0x00;
P3PU = 0x30; //P3.4,P3.5使能内部4.1K上拉电阻
P40 = 0;
AUXR |= 0x80; //定时器时钟1T模式
TMOD = 0; //设置定时器模式
TL0 = 0xff; //设置定时初始值
TH0 = 0xff; //设置定时初始值
TMOD = 0X04;
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
INTCLKO &= 0xfe; //T0不输出时钟
EA = 1;
while (1)
{
}
}
void Time0_ISR(void) interrupt TMR0_VECTOR//定时器0中断函数
{
P6= ~P6;
}
好久没有更新了,今天把写好的例程发一下 本帖最后由 lezjin 于 2024-6-28 20:26 编辑
五。在时间片调用中增加了一个UART2发送给电脑测试,
void UartInit(void)
{
COMx_InitDefine uartinfo;
uartinfo.UART_Mode = UART_8bit_BRTx;
uartinfo.UART_BRT_Use = BRT_Timer2;
uartinfo.UART_BaudRate = 115200L;
uartinfo.UART_RxEnable = ENABLE;
uartinfo.Morecommunicate = ENABLE;
uartinfo.BaudRateDouble = DISABLE;
UART_Configuration(UART2, &uartinfo);
NVIC_UART2_Init(ENABLE, Priority_1);
UART2_SW(UART2_SW_P46_P47);
}
void testuart2(void)
{
PrintString2("Test uart2 !\r\n");
配置串口2使用了库函数,在主函数中每5秒调用测试函数
六。矩阵按键 行列扫描返回端口数值,然后 采用论坛三行代码,返回键值后判断按键简单点灯灭灯测试效果,主函数每20毫秒扫描一次,可以正常点亮熄灭,健壮性有待后续验证。
#define KEY P0
static void KeyDelay(void)
{
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
static unsigned char KeyScan()
{
unsigned char keynum = 0xff ;
KEY = 0xf0;
KeyDelay();
keynum = KEY & 0xf0;
KEY = 0x0f;
KeyDelay();
keynum |= (KEY & 0x0f);
// keynum = keynum ^ 0xff;
return keynum;
}
unsigned charKeyVal(void)
{
static unsigned char s_keyStateLast;
static unsigned char s_keyStateNow;
unsigned char keyval=0;
unsigned char readKeyPort=0;
readKeyPort = (KeyScan()) ^ 0xff; //1111 11111
s_keyStateNow = readKeyPort & (readKeyPort ^ s_keyStateLast);
s_keyStateLast = readKeyPort;
keyval = s_keyStateNow;
return keyval;
}
void MatrixKey(void)
{
unsigned char key =KeyVal();
if (key == 0x81)
P65 = 0;
if (key== 0x82)
P65 = 1;
if (key == 0x84)
P66 = 0;
if (key == 0x88)
P66 = 1;
if (key == 0x41)
P67 = 0;
if (key == 0x42)
P67 = 1;
}
static Task_t g_task[] =
{
//状态计数重装 函数
{0,20, 20,MatrixKey},
/* Add new task here */
};
页:
[1]
2