• (原创)TWR MCF51CN 总线时钟控制和串口测试程序编写


    昨天下午开始熟悉飞思卡尔的TWR(塔)系统,MCU是CodeFire V1 核的MCF51CN。TWR系统碟所附带的lab均是搭载了MQX,而且网络上的资源少之又少。为了学习这款MCU,决定还是看datasheet然后编写各个模块的代码。由于时间紧张,详细寄存器定义和使用方法以后再添上。

    1、MCG

    MCF51CN的时钟比较复杂,与以往的16位MCU不用,MCF51CN的多用途时钟生成模块(Multipurpose Clock Generator, MCG) 比以往的MCU时钟控制更为复杂、精细,带来的是更多的选择和更低的功耗(在我看来是更为麻烦的编程……)。

    MCG模块图

    时钟源(Reference clock)主要来自外部的晶振(TWR51 上是25MHz)和片内时钟。为了更稳定的时钟输出,除了用来倍频的PLL外,还有一个FLL,就是“锁频环”。

    MCU复位后,各种寄存器的默认值是在FEI(FLL Engaged Internal, 内部时钟参考FLL)模式下,默认输出是16Mhz。根据手册上的公式,FLL的倍频系数为512,Bus Divider 为2,这样可以推断出Internal Clock的频率为31.25KHz。

    MCG给定了模块工作的几个模式,各个模式之间转换图如下

    红线所示的就是如何从默认的FEI转到PEE(外部锁相环)。

    TWR自带的外部晶振为25MHz,如果想把总线频率倍频到50MHz,可以通过以下的方式

     1 // CLK初始化,默认是FEI mode, 调整到PEE 
    2 // BUS CLK = 50M
    3 void CLK_init_50MHz(void)
    4 {
    5
    6 //1. First, FEI must transition to FBE mode:
    7 //a) MCGC2 = 0x36 (%00110110)
    8 // BDIV (bits 7 and 6) set to %00, or divide-by-1
    9 // RANGE (bit 5) set to 1 because the frequency of 8 MHz is within the high frequency range
    10 // HGO (bit 4) set to 1 to configure the crystal oscillator for high gain operation
    11 // EREFS (bit 2) set to 1, because a crystal is being used
    12 // ERCLKEN (bit 1) set to 1 to ensure the external reference clock is active
    13 MCGC2 = MCGC2_EREFS_MASK | MCGC2_ERCLKEN_MASK | MCGC2_RANGE_MASK | MCGC2_HGO_MASK;
    14
    15
    16 //b) Loop until OSCINIT (bit 1) in MCGSC is 1, indicating the crystal selected by the EREFS bit
    17 //has been initialized.
    18 while (!(MCGSC & MCGSC_OSCINIT_MASK))
    19 ;
    20
    21 //c) Because RANGE = 1, set DIV32 (bit 4) in MCGC3 to allow access to the proper RDIV bits
    22 //while in an FLL external mode.
    23 MCGC3 |= MCGC3_DIV32_MASK;
    24
    25 //d) MCGC1 = 0x98 (%10011000)
    26 // CLKS (bits 7 and 6) set to %10 to select external reference clock as system clock source
    27 // RDIV (bits 5-3) set to %011, or divide-by-256 because 8MHz / 256 = 31.25 kHz that is in
    28 //the 31.25 kHz to 39.0625 kHz range required by the FLL
    29 // IREFS (bit 2) cleared to 0, selecting the external reference clock
    30 MCGC1 = (0b10 << MCGC1_CLKS_BITNUM) // CLKS = 10 -> external reference clock
    31 | (0b100 << MCGC1_RDIV_BITNUM); // RDIV = 2^4 -> 25MHz/16 = 1.5625 MHz for PLL
    32
    33
    34
    35 // wait for Reference Status bit to update
    36 while (!( MCGSC & MCGSC_IREFST_MASK))
    37 ;
    38
    39 // and for clock status bits to update
    40 while (( MCGSC & MCGSC_CLKST_MASK) != (0b10 << MCGSC_CLKST_BITNUM))
    41 ;
    42
    43
    44 // switch from FBE to PBE (PLL bypassed internal) mode
    45 // set PLL multi 50MHz amd select PLL
    46 MCGC3 = (0b1000<< MCGC3_VDIV_BITNUM) | MCGC3_PLLS_MASK;
    47
    48 // wait for PLL status bit and LOCK bit
    49 while (!( MCGSC & MCGSC_PLLST_MASK) && !( MCGSC & MCGSC_LOCK_MASK))
    50 ;
    51
    52 //switch from PBE to PEE (PLL enabled external mode)
    53 MCGC1 &= ~(0b11 << MCGC1_CLKS_BITNUM);
    54
    55 /* Wait for clock status bits to update */
    56 while (( MCGSC & MCGSC_CLKST_MASK )!= (0b11<< MCGSC_CLKST_BITNUM))
    57 ;
    58 // FEE mode entered
    59 }

    1、SCI

    (1) 设置GPIO复用,将PTD2改为TXD2,PTD3改RXD3。因为TWR系统将顶板MCF51CN的SCI2通过PCI接口接到底板的RS232上,所以可以需要设置但是SCI2。

    (2) 设置波特率。总线时钟为50M,将SBR设置为651,可以得到近似的9600b/s的波特率。8位数据模式,不使用校验位

    (3) 中断设置。不使用中断,因为只是简单测试串口发送只需查询方式即可。

     1 void SCI_init(void)
    2 {
    3 //RXD2_DIR = 0;//in
    4 //TXD2_DIR = 1;//out
    5 PTDPF2_D2 = 2;//PTD_PTD2 as TXD2
    6 PTDPF2_D3 = 2;//PTD_PTD2 as RXD2
    7
    8 //SCI baud rate equals SCI module clock/(16 × BR)
    9 //50000000/(326*16) = 9615 0x146
    10 //50000000/(651*16) = 4800 0x28b
    11 SCI2BDH = 0x01;//000-00010
    12 SCI2BDL = 0x46;
    13
    14 SCI2C1 = 0x00;//0000 0010:not Loop mode or single-wire mode, start + 8 data bits (lsb first) + stop, No Parity enabled, even
    15 SCI2C2 = 0x00;//disable transmit & receive interrupt; not start transmi:SCI2C2_TE=0;
    16 SCI3C3 = 0x00;
    17
    18 }

    发送单个字符函数

    1 void SCI_send(unsigned char sendchar)
    2 {
    3 while(SCI2S1_TC==0)//transmission doesnt end
    4 ;
    5 SCI2D = sendchar;
    6 SCI2C2_TE = 1;//send
    7 }

    发送字符串函数

    1 void SCI_sendmsg(unsigned char * msg,unsigned char cnt)
    2 {
    3 unsigned char count=0;
    4 for(count=0;count<cnt;count++)
    5 {
    6 SCI_send(*(msg+count));
    7 }
    8 }

    最后main函数,记得要在for循环里面喂看门狗,防止程序跑飞

     1 void main(void) 
    2 {
    3 DisableInterrupts;
    4 //variable
    5 unsigned char msg1[12] ={"hello! rcq!\n"};
    6 unsigned char msg2[27] ={"abcedfghigklmnopqrstvuwxyz\n"};
    7 unsigned char msg3[49] ={"这是SCI 测试 超群天晴 2012年 3月17日20:52:41\n"};
    8 // sys init
    9 CLK_init_50MHz();
    10 LED_init();
    11 SCI_init();
    12 //function body
    13 SCI_sendmsg(msg1,12);
    14 delay();
    15 SCI_sendmsg(msg2,27);
    16 delay();
    17 SCI_sendmsg(msg3,49);
    18 delay();
    19 SCI_test();
    20 delay();
    21 for(;;)
    22 {
    23 __RESET_WATCHDOG(); /* feeds the dog */
    24 }
    25 }


    连上串口调试助手,显示结果






  • 相关阅读:
    hiho一下121周 后缀数组二·重复旋律2
    codeforces 381 D Alyona and a tree(倍增)(前缀数组)
    hiho一下120周 后缀数组一·重复旋律
    POJ 2893 M × N Puzzle(树状数组求逆序对)
    Java高并发-无锁
    Java高并发-Java内存模型和线程安全
    Linux用户权限集中管理方案
    CentOS下sudo的使用和sudoers配置
    Java高并发-多线程基础
    Java高并发-概念
  • 原文地址:https://www.cnblogs.com/surpassal/p/2404052.html
Copyright © 2020-2023  润新知