找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1465|回复: 1
打印 上一主题 下一主题
收起左侧

不借助工具,使用串口输出对STC8A8K64S4A12的IRTRIM值进行标定

[复制链接]
跳转到指定楼层
楼主
ID:912806 发表于 2021-11-11 19:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
STC8A8K64S4A12这个型号的MCU, 因为没有固化的频率调节值, 要么在STC-ISP烧录时设置写入, 要么通过idata高地址区读取, 这对于Linux下的SDCC用户就非常不方便, 既不能用STC-ISP, 写入SDCC编译后的程序也无法在idata区读取对应的值. 相比较STC8A8K64D4就方便许多, 在xdata区域有固定的值可以读取.
那么对于Linux下的SDCC用户, 如何去确定这个频率调节值? 一个办法是通过逻辑分析仪去标定, 但是如果没有逻辑分析仪呢? 还可以通过指定的串口波特率去标定.

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

编译这个程序后写入STC8A8K64S4A12, 使用USB2TTL连接串口1, 波特率9600, 观察输出的字符串.
当实际频率接近预设的频率时, 能观察到非乱码的输出. 取非乱码区间的中间点对应的值, 就可以作为此频率对应的IRTRIM和LIRTRIM值.

代码已经添加了对应的宏处理, 可以兼容SDCC和Keil C51环境.
  1. /*****************************************************************************/
  2. /**
  3. * \file        itrim_detect.c
  4. * \brief       使用固定波特率串口输出标定STC8A8K64S4A12各频率的ITRIM
  5. * \version     v0.1
  6. ******************************************************************************/

  7. /*****************************************************************************/
  8. /**
  9. * \brief       自适应SDCC和Keil C51的宏处理
  10. ******************************************************************************/

  11. #if defined (SDCC) || defined (__SDCC)
  12. # define SBIT(name, addr, bit)  __sbit  __at(addr+bit)                    name
  13. # define SFR(name, addr)        __sfr   __at(addr)                        name
  14. # define SFRX(name, addr)       __xdata volatile unsigned char __at(addr) name
  15. #define NOP() __asm NOP __endasm


  16. #elif defined __CX51__
  17. # define SBIT(name, addr, bit)  sbit  name = addr^bit
  18. # define SFR(name, addr)        sfr   name = addr
  19. # define SFRX(name, addr)       volatile unsigned char xdata name _at_ addr
  20. extern void _nop_ (void);
  21. #define NOP() _nop_()

  22. /** default
  23.   * unrecognized compiler
  24. */
  25. #else
  26. # warning unrecognized compiler
  27. # define SBIT(name, addr, bit)  volatile bool           name
  28. # define SFR(name, addr)        volatile unsigned char  name
  29. # define SFRX(name, addr)       volatile unsigned char  name

  30. #endif

  31. /*****************************************************************************/
  32. /**
  33. * \brief       代码中涉及的寄存器
  34. ******************************************************************************/

  35. SBIT(TI,                0x98, 1);

  36. SFR(PCON,               0x87);
  37. SFR(AUXR,               0x8E);
  38. SFR(SCON,               0x98);
  39. SFR(SBUF,               0x99);
  40. SFR(LIRTRIM,            0x9E);
  41. SFR(IRTRIM,             0x9F);
  42. SFR(P_SW2,              0xBA);
  43. SFR(T2H,                0xD6);
  44. SFR(T2L,                0xD7);

  45. SFRX(CLKDIV,            0xfe01);
  46. SFRX(IRC24MCR,          0xfe02);

  47. static const char hexTable[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};

  48. /*****************************************************************************/
  49. /**
  50. * \brief       时钟和串口1初始化
  51. ******************************************************************************/
  52. void clock_init()
  53. {
  54.   // [  BAH,0,0x00]: 外设端口切换控制寄存器2,串口2/3/4,I2C,比较器
  55.   P_SW2      = 0x80;
  56.   // [FE01H,1,0x00]: 时钟分频寄存器,ISP可能写入预设值
  57.   CLKDIV     = 0x00;
  58.   // [  9EH,0,0x00]: IRC频率微调寄存器, ISP可能写入预设值
  59.   LIRTRIM    = 0x00;
  60.   // [  BAH,0,0x00]: 外设端口切换控制寄存器2,串口2/3/4,I2C,比较器
  61.   P_SW2      = 0x00;

  62.   // [  87H,0,0x30]: 电源控制寄存器
  63.   PCON       = 0xB0;
  64.   // [  98H,0,0x00]: 串口1控制寄存器
  65.   SCON       = 0x50;
  66.   // [  8EH,0,0x01]: 辅助寄存器
  67.   AUXR       = 0x15;
  68. }

  69. /*****************************************************************************/
  70. /**
  71. * \brief       不同频率对应的串口初始化程序
  72. ******************************************************************************/
  73. void uart_init_18m_9600()
  74. {
  75.     // [  D6H,0,0x00]: 定时器2高字节
  76.     T2H        = 0xFE;
  77.     // [  D7H,0,0x00]: 定时器2低字节
  78.     T2L        = 0x2B;
  79. }

  80. void uart_init_22m1184_9600()
  81. {
  82.   // [  D6H,0,0x00]: 定时器2高字节
  83.   T2H        = 0xFD;
  84.   // [  D7H,0,0x00]: 定时器2低字节
  85.   T2L        = 0xC0;
  86. }

  87. void uart_init_24m_9600()
  88. {
  89.   // [  D6H,0,0x00]: 定时器2高字节
  90.   T2H        = 0xFD;
  91.   // [  D7H,0,0x00]: 定时器2低字节
  92.   T2L        = 0x8F;
  93. }

  94. void uart_init_28m_9600()
  95. {
  96.   // [  D6H,0,0x00]: 定时器2高字节
  97.   T2H        = 0xFD;
  98.   // [  D7H,0,0x00]: 定时器2低字节
  99.   T2L        = 0x26;
  100. }

  101. void uart_init_32m_9600()
  102. {
  103.   // [  D6H,0,0x00]: 定时器2高字节
  104.   T2H        = 0xFC;
  105.   // [  D7H,0,0x00]: 定时器2低字节
  106.   T2L        = 0xBE;
  107. }

  108. /*****************************************************************************/
  109. /**
  110. * \brief       通过修改IRTRIM和LIRTRIM调节内部时钟频率
  111. ******************************************************************************/
  112. void trim_freq(unsigned char trim, unsigned char litrim)
  113. {
  114.   IRTRIM = trim;
  115.   LIRTRIM = litrim;
  116.   while(!(IRC24MCR & 0x01));
  117. }

  118. void PrintChar(unsigned char dat)
  119. {
  120.   SBUF = dat;
  121.   while(!TI);
  122.   TI = 0;
  123. }

  124. void PrintHex(unsigned char hex)
  125. {
  126.   PrintChar(hexTable[hex >> 4]);
  127.   PrintChar(hexTable[hex & 0xF]);
  128. }

  129. void PrintString(unsigned char *str)
  130. {
  131.   while (*str != '\0')
  132.   {
  133.     SBUF = *str;
  134.     while(!TI);
  135.     TI = 0;     /* clear */
  136.     str++;
  137.   }
  138. }

  139. void Delay100ms()                //@22.1184MHz
  140. {
  141.   unsigned char j, k;
  142.   j = 100;
  143.   k = 228;
  144.   do
  145.   {
  146.     while (--k);
  147.   } while (--j);
  148. }

  149. void DetectItrim(unsigned char *str)
  150. {
  151.   unsigned char i, j;
  152.   do
  153.   {
  154.     j = 3;
  155.     do
  156.     {
  157.       trim_freq(i, j);
  158.       PrintHex(IRTRIM);
  159.       PrintChar(0x20);
  160.       PrintHex(LIRTRIM);
  161.       PrintChar(0x20);
  162.       PrintString(str);
  163.       Delay100ms();
  164.     } while (--j);
  165.   } while(--i);
  166. }

  167. void main()
  168. {
  169.   clock_init();

  170.   while(1)
  171.   {
  172.     uart_init_18m_9600();
  173.     DetectItrim(" 18MHz 9600\r\n");
  174.     uart_init_22m1184_9600();
  175.     DetectItrim(" 22.1184MHz 9600\r\n");
  176.     uart_init_24m_9600();
  177.     DetectItrim(" 24MHz 9600\r\n");
  178.     uart_init_28m_9600();
  179.     DetectItrim(" 28MHz 9600\r\n");
  180.     uart_init_32m_9600();
  181.     DetectItrim(" 32MHz 9600\r\n");
  182.   }
  183. }
复制代码




评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:519089 发表于 2021-11-16 11:33 | 只看该作者
51 用linux啊,,,简直没谁了。。。。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表