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环境.- /*****************************************************************************/
- /**
- * \file itrim_detect.c
- * \brief 使用固定波特率串口输出标定STC8A8K64S4A12各频率的ITRIM
- * \version v0.1
- ******************************************************************************/
- /*****************************************************************************/
- /**
- * \brief 自适应SDCC和Keil C51的宏处理
- ******************************************************************************/
- #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
- #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;
- }
- /*****************************************************************************/
- /**
- * \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() //@22.1184MHz
- {
- 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");
- }
- }
复制代码
|