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");
- }
- }
復制代碼
|