STC8A8K64S4A12因为没有固化的频率调节值, 要么在STC-ISP烧录时设置写入, 要么通过idata高地址读取, 这对于Linux下的SDCC用户就非常不方便, 既不能用STC-ISP, 写入SDCC编译后的程序也无法在idata区读取对应的值.

那么对于Linux下的SDCC用户, 如何去确定这个频率调节值? 一个办法是通过逻辑分析仪去标定, 但是如果没有逻辑分析仪呢? 如果对频率要求不严格的话, 可以直接通过代码输出串口数据去标定.

因为串口波特率与系统时钟是关联的, 假定当前系统时钟频率固定, 那么对应一个给定的波特率例如9600, 对应的寄存器值是固定的, 如果芯片按这个值运行, 只有当系统时钟频率与预设的值接近(误差5%内), 上位机才能解码出正确的输出, 其它情况看到的都是乱码. 根据这个特性, 如果在代码中不断调节频率, 同时输出当时的IRTRIM和LIRTRIM值, 根据乱码和正常接收的情况, 就能判断出对应此频率的IRTRIM和LIRTRIM值.

编译这个程序后写入STC8A8K64S4A12, 使用USB2TTL连接串口1, 波特率9600, 观察输出的字符串.

当实际频率接近预设的频率时, 能观察到正常的输出. 取非乱码区间的中间点对应的值, 就可以作为此频率对应的IRTRIM和LIRTRIM值.

代码已经添加了对应的宏处理, 兼容SDCC和Keil C51编译

/*****************************************************************************/
/**
* \file itrim_detect.c
* \brief 使用固定波特率串口输出标定STC8A8K64S4A12各频率的ITRIM
* \version v0.1
******************************************************************************/ /*****************************************************************************/
/**
* \brief 自适应SDCC和Keil C51的宏处理
******************************************************************************/ /** SDCC - Small Device C Compiler
* http://sdcc.sf.net
*/
#if defined (SDCC) || defined (__SDCC)
# define SBIT(name, addr, bit) __sbit __at(addr+bit) name
# define SFR(name, addr) __sfr __at(addr) name
# define SFRX(name, addr) __xdata volatile unsigned char __at(addr) name
#define NOP() __asm NOP __endasm /** Keil C51
* http://www.keil.com
*/
#elif defined __CX51__
# define SBIT(name, addr, bit) sbit name = addr^bit
# define SFR(name, addr) sfr name = addr
# define SFRX(name, addr) volatile unsigned char xdata name _at_ addr
extern void _nop_ (void);
#define NOP() _nop_() /** default
* unrecognized compiler
*/
#else
# warning unrecognized compiler
# define SBIT(name, addr, bit) volatile bool name
# define SFR(name, addr) volatile unsigned char name
# define SFRX(name, addr) volatile unsigned char name #endif /*****************************************************************************/
/**
* \brief 代码中涉及的寄存器
******************************************************************************/ SBIT(TI, 0x98, 1); SFR(PCON, 0x87);
SFR(AUXR, 0x8E);
SFR(SCON, 0x98);
SFR(SBUF, 0x99);
SFR(LIRTRIM, 0x9E);
SFR(IRTRIM, 0x9F);
SFR(P_SW2, 0xBA);
SFR(T2H, 0xD6);
SFR(T2L, 0xD7); SFRX(CLKDIV, 0xfe01);
SFRX(IRC24MCR, 0xfe02); static const char hexTable[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; /*****************************************************************************/
/**
* \brief 时钟和串口1初始化
******************************************************************************/
void clock_init()
{
// [ BAH,0,0x00]: 外设端口切换控制寄存器2,串口2/3/4,I2C,比较器
P_SW2 = 0x80;
// [FE01H,1,0x00]: 时钟分频寄存器,ISP可能写入预设值
CLKDIV = 0x00;
// [ 9EH,0,0x00]: IRC频率微调寄存器, ISP可能写入预设值
LIRTRIM = 0x00;
// [ BAH,0,0x00]: 外设端口切换控制寄存器2,串口2/3/4,I2C,比较器
P_SW2 = 0x00; // [ 87H,0,0x30]: 电源控制寄存器
PCON = 0xB0;
// [ 98H,0,0x00]: 串口1控制寄存器
SCON = 0x50;
// [ 8EH,0,0x01]: 辅助寄存器
AUXR = 0x15;
} /*****************************************************************************/
/**
* \brief 不同频率对应的串口初始化程序
******************************************************************************/
void uart_init_18m_9600()
{
// [ D6H,0,0x00]: 定时器2高字节
T2H = 0xFE;
// [ D7H,0,0x00]: 定时器2低字节
T2L = 0x2B;
} void uart_init_22m1184_9600()
{
// [ D6H,0,0x00]: 定时器2高字节
T2H = 0xFD;
// [ D7H,0,0x00]: 定时器2低字节
T2L = 0xC0;
} void uart_init_24m_9600()
{
// [ D6H,0,0x00]: 定时器2高字节
T2H = 0xFD;
// [ D7H,0,0x00]: 定时器2低字节
T2L = 0x8F;
} void uart_init_28m_9600()
{
// [ D6H,0,0x00]: 定时器2高字节
T2H = 0xFD;
// [ D7H,0,0x00]: 定时器2低字节
T2L = 0x26;
} void uart_init_32m_9600()
{
// [ D6H,0,0x00]: 定时器2高字节
T2H = 0xFC;
// [ D7H,0,0x00]: 定时器2低字节
T2L = 0xBE;
} void uart_init_33m1776_9600()
{
// [ D6H,0,0x00]: 定时器2高字节
T2H = 0xFC;
// [ D7H,0,0x00]: 定时器2低字节
T2L = 0xA0;
} /*****************************************************************************/
/**
* \brief 通过修改IRTRIM和LIRTRIM调节内部时钟频率
******************************************************************************/
void trim_freq(unsigned char trim, unsigned char litrim)
{
IRTRIM = trim;
LIRTRIM = litrim;
while(!(IRC24MCR & 0x01));
} void PrintChar(unsigned char dat)
{
SBUF = dat;
while(!TI);
TI = 0;
} void PrintHex(unsigned char hex)
{
PrintChar(hexTable[hex >> 4]);
PrintChar(hexTable[hex & 0xF]);
} void PrintString(unsigned char *str)
{
while (*str != '\0')
{
SBUF = *str;
while(!TI);
TI = 0; /* clear */
str++;
}
} void Delay100ms()
{
unsigned char j, k;
j = 100;
k = 228;
do
{
while (--k);
} while (--j);
} void DetectItrim(unsigned char *str)
{
unsigned char i, j;
do
{
j = 3;
do
{
trim_freq(i, j);
PrintHex(IRTRIM);
PrintChar(0x20);
PrintHex(LIRTRIM);
PrintChar(0x20);
PrintString(str);
Delay100ms();
} while (--j);
} while(--i);
} void main()
{
clock_init(); while(1)
{
uart_init_18m_9600();
DetectItrim(" 18MHz 9600\r\n");
uart_init_22m1184_9600();
DetectItrim(" 22.1184MHz 9600\r\n");
uart_init_24m_9600();
DetectItrim(" 24MHz 9600\r\n");
uart_init_28m_9600();
DetectItrim(" 28MHz 9600\r\n");
uart_init_32m_9600();
DetectItrim(" 32MHz 9600\r\n");
uart_init_33m1776_9600();
DetectItrim(" 33.1776MHz 9600\r\n");
}
}

我手里的这块STC8A8K64S4实测结果是这样的

IRTRIM  LIRTRIM  FOSC     BAUD
0E 02 18MHz
53 03 22.1184MHz
74 03 24MHz
F3 02 32MHz
FC 01 33.1776MHz

STC8A8K64S4A12内部时钟的IRTRIM和LIRTRIM简单标定的更多相关文章

  1. stm32 时钟配置——外部时钟倍频、内部时钟倍频 【worldsing笔记】

    stm32可选的时钟源 在STM32中,可以用内部时钟,也可以用外部时钟,在要求进度高的应用场合最好用外部晶体震荡器,内部时钟存在一定的精度误差. 准确的来说有4个时钟源可以选分别是HSI.LSI.H ...

  2. STM32内部时钟设置-寄存器版

    STM32寄存器版本——内部时钟设置 同时要记得把延时初始化函数设置好 //系统时钟初始化函数 //pll:选择的倍频数,从2开始,最大值为16 //pll:选择的倍频数,这里使用内部时钟,PLL为4 ...

  3. Oracle恢复ORA-00600: 内部错误代码, 参数: [kcratr_scan_lastbwr] 问题的简单解决

    Oracle恢复ORA-00600: 内部错误代码, 参数: [kcratr_scan_lastbwr] 1. 简单处理 sqlplus / as sysdba startup mount recov ...

  4. 转:Linux内部的时钟处理机制全面剖析

    Linux内部的时钟处理机制全面剖析 在 Linux 操作系统中,很多活动都和时间有关,例如:进程调度和网络处理等等.所以说,了解 Linux 操作系统中的时钟处理机制有助于更好地了解 Linux 操 ...

  5. 史上最简单的js+css3实现时钟效果

    今天我看到百度搜索的时间那个效果不错,于是就产生了模仿一下的效果,不过为了节省时间,就随便布了下局,废话不多说,先看看效果吧,顺便把百度的效果也拿过来. 对比样子差了好多啊,但是基本功能都是实现了的, ...

  6. STM32F030 启用内部晶振并配置系统时钟为48M

    在文件 system_stm32f0xx.c 里的函数 static void SetSysClock(void) { if (HSEStatus == (uint32_t)0x01) // 存在外部 ...

  7. STC8A,STC8G,STC8H系列的IRC内部振荡源频率调节

    从STC15开始, 宏晶就在内置RC震荡源(内置时脉, 宏晶称之为IRC)这条路上越走越远. STC15这一代仅仅是"有", 精度和漂移差强人意. 从STC8开始对IRC的调节就越 ...

  8. C# ADO.NET编写简单的图书馆管理软件

    使用软件: Microsoft SQL Server 2012 Microsoft Visual Studio 2012 本文地址: http://www.cnblogs.com/go2bed/ 参考 ...

  9. Cotex-M3内核STM32F10XX系列时钟及其配置方法

    一.背景 最近做个项目,需要使用STM32,还是以前一样的观点,时钟就是MCU心脏,供血即时钟频率输出,想要弄明白一个MCU,时钟是一个非常好的切入点.言归正传,网上已经有太多大神详述过STM32的详 ...

  10. Linux驱动设计—— 中断与时钟

    中断和时钟技术可以提升驱动程序的效率 中断 中断在Linux中的实现 通常情况下,一个驱动程序只需要申请中断,并添加中断处理函数就可以了,中断的到达和中断函数的调用都是内核实现框架完成的.所以程序员只 ...

随机推荐

  1. 使用WTM框架创建博客系统后台并在云服务器发布

    阅读导航 关于lqclass.com 博客后台前后端部署 2.1 已部署访问链接 2.2 nginx 部署 2.2.1 后台后端发布 2.2.2 后台前端发布 2.2.3 云服务器部署 下次分享 1. ...

  2. 如何在Typora中跳转到文本内的指定位置?

    1.问题 网上写的使用HTML锚点,在typora并不适用 如 跳转 你好 2.解决 参考链接 https://segmentfault.com/q/1010000018057010 https:// ...

  3. 初次安装Linux 1Panel面板体验

    初次安装Linux 1Panel面板体验 1Panel是Linux下的一款服务器管理工具.和宝塔相比更加轻量化.相比之下各有优点,本文让我们一起来安装1Panel面板. 面板优势 快速建站 :深度集成 ...

  4. window-子系统-ubuntu

    window-子系统-ubuntu 1. 背景 提供类Linux开发环境(命令行.文件系统.进程管理.网路) 2. 安装 A. wsl 安装 下载链接: https://wslstorestorage ...

  5. [转帖]配置cri-docker使kubernetes1.24以docker作为运行时

    从kubernetes 1.24开始,dockershim已经从kubelet中移除,但因为历史问题docker却不支持kubernetes主推的CRI(容器运行时接口)标准,所以docker不能再作 ...

  6. [转帖]TiDB系统调参实战经验

    https://tidb.net/blog/c9466c40#TiDB%E7%B3%BB%E7%BB%9F%E8%B0%83%E5%8F%82%E5%AE%9E%E6%88%98%E7%BB%8F%E ...

  7. [转帖]使用Linux命令快速查看某一行

      原创:打码日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处. 简介# 当年,我还是Linux菜鸟的时候,就在简历上写着精通Linux命令了,而当面试官问我"如何快速查看 ...

  8. CentOS7 和 CentOS8 安装 rusers-server 然后使用LR 实时监控Linux主机性能的办法

    LR 能够通过RPC 的工具 实时获取 被压测机器的 性能表现 但是需要安装几个组件. CentOS6 时期比较简单 可以通过网上 下载rstatd 的tar 包离线安装即可 但是发现CentOS7 ...

  9. 神经网络优化篇:详解超参数调试的实践:Pandas VS Caviar(Hyperparameters tuning in practice: Pandas vs. Caviar)

    超参数调试的实践 如今的深度学习已经应用到许多不同的领域,某个应用领域的超参数设定,有可能通用于另一领域,不同的应用领域出现相互交融.比如,曾经看到过计算机视觉领域中涌现的巧妙方法,比如说Confon ...

  10. SP5464 CT - Counting triangles 题解

    题目翻译 题意 有一个网格,左上角是 \((0,0)\),右上角是 \((x,y)\).求这个网格中一共有多少个等腰直角三角形. 输入 第一行给定一个 \(c\),表示有 \(c\) 组数据. 后面 ...