(原创)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 }
连上串口调试助手,显示结果