为了测试STC8F/A的PCA脉冲测量脉宽,需要一个精确的外部时钟源。参考STC-ISP范例程序进行了测试,以下程序实现了选择外部时钟源。
/*
STC8F/A系统时钟源选择外部时钟串口测试程序
外部晶振为11.0592M,串口波特率设置在115200
验证方法:
1 编译后 STC-ISP下载内部IRC频率可选任意值
2 串口设置成“编程完成后自动打开串口”
3 串口波特率设置成115200
4 下载完成后串口接受区自动显示“STC8系统时钟源串口测试!”
5 可在发送缓冲区发送数据,数据可大于接收缓存16字节,接收区能正常显示
证明选择外部晶振时钟源成功!
*/
#include "reg51.h"
#include "intrins.h"
//#include "STC8Axx.h"
#define CKSEL (*(unsigned char volatile xdata *)0xfe00)
#define CKDIV (*(unsigned char volatile xdata *)0xfe01)
#define IRC24MCR (*(unsigned char volatile xdata *)0xfe02)
#define XOSCCR (*(unsigned char volatile xdata *)0xfe03)
#define IRC32KCR (*(unsigned char volatile xdata *)0xfe04)
#define FOSC 11059200UL
#define BRT (65536 - FOSC / 115200 / 4)
sfr AUXR = 0x8e;
sfr P_SW2 = 0xba;
bit busy;
char wptr;
char rptr;
char buffer[16];
void UartIsr() interrupt 4
{
if (TI)
{
TI = 0;
busy = 0;
}
if (RI)
{
RI = 0;
buffer[wptr++] = SBUF;
wptr &= 0x0f;
}
}
void UartInit()
{
SCON = 0x50;
TMOD = 0x00;
TL1 = BRT;
TH1 = BRT >> 8;
TR1 = 1;
AUXR = 0x40;
wptr = 0x00;
rptr = 0x00;
busy = 0;
}
void UartSend(char dat)
{
while (busy);
busy = 1;
SBUF = dat;
}
void UartSendStr(char *p)
{
while (*p)
{
UartSend(*p++);
}
}
void main()
{
// P_SW2 = 0x80;
// CKSEL = 0x00; //选择内部IRC ( 默认 )
// P_SW2 = 0x00;
P_SW2 = 0x80;
XOSCCR = 0xc0; //启动外部晶振
while (!(XOSCCR & 1)); //等待时钟稳定
CKDIV = 0x00; //时钟不分频
CKSEL = 0x01; //选择外部晶振
P_SW2 = 0x00;
/*
P_SW2 = 0x80;
IRC32KCR = 0x80; //启动内部32K IRC
while (!(IRC32KCR & 1)); //等待时钟稳定
CKDIV = 0x00; //时钟不分频
CKSEL = 0x03; //选择内部32K
P_SW2 = 0x00;
*/
// TMOD = 0x00; //模式0
// TL0 = 0x66; //65536-11.0592M/12/1000
// TH0 = 0xfc;
// TR0 = 1; //启动定时器
// INTCLKO = 0x01; //使能时钟输出
UartInit();
ES = 1;
EA = 1;
UartSendStr("STC8系统时钟源串口测试!\r\n");
while (1)
{
if (rptr != wptr)
{
UartSend(buffer[rptr++]);
rptr &= 0x0f;
}
}
}
上图红色划线的晶振频率选择对本例无影响,本例11.0592M@115200.
另附wptr的解释例程(VSCODE下编译):
#include <stdio.h>
unsigned char i,wptr;
void main()
{
printf("wptr的解释\n");
for(i=0;i<24;i++)
{
printf("i=%2d wptr=%2d\n",i,wptr);
wptr &= 0x0f;
wptr++;
}
}
输出结果: