/**** 注意,由于网速原因现在暂时无法贴图,请谅解。 ****/
首先说句抱歉,可能让正在学习COLDFIRE系列处理器的朋友和经常关注本博的朋友失望了,我的确很久没更新过博客,但是并不代表不更新了,这个系列还是要坚持写下去。因为现在CF系列处理器的使用还是较少的,网上资料也不多,教材也只有清华出过一本中文版的(似乎质量……),有些问题凭DATASHEET和教材还是没法处理,这样会走很大的弯路,我写这个系列主要不是什么都讲,而是把自己调试的一些心得都写出来,以免让朋友们再犯同样的错误浪费时间。
对于UART这个概念,相信各位是再熟悉不过了,什么意思我就不再解释了,毕竟网上“精辟”的定义太多了。现在使用CF的UART,主要还是使用三线和电脑作RS-232通信,当然也可以和其他单片机连接,这个大家都很熟悉。
一、介绍
以我个人目前正在使用的MCF52235为例,这个单片机有3个UART,分别为UART0-UART2,由于三个模块的配置基本完全一样,所以DATASHEET上也只是大略得讲了讲。
UART每个模块都包含:
·串行通信通道
·可编程时钟发生器
·中断控制和DMA
·内部通道控制逻辑
其中DMA和中断以后在DMA和中断控制器里再讲。
图一 模块结构图
UART每个模块有以下特性:
·可选择使用内部时钟或者外部时钟
·全双工同步异步收发
·双缓冲发,四缓冲收
·收发器独立编程
·5-8个带奇偶校验数据,奇偶校验或者无校验,1、1.5或2个停止位
·四种模式
·自动唤醒
·四个可屏蔽中断
·DMA
·错误检测
UART模块的外部引脚有UTXDn,URXDn,/UCTSn,/URTSn。前两个大家都很熟悉的,后两个分别为CLEAR-TO-SEND和REQUEST-TO-SEND,为控制和状态信号。我暂时没用到,就不多写了。
二、寄存器配置说明
UART模块每个通道有10余个寄存器,当然并不是每个都能用到,只要是重点的,我都会详细解释并给出图,如果需要更详细的,那就去看DATASHEET或者看清华的书(MCF5282)。
1、模式寄存器1 UMR1n
图二 模式寄存器1
这个寄存器很重要,初始化时要注意,必须使用命令寄存器把模式寄存器指针清零才可以开始,而且模式寄存器1和模式寄存器2必须顺序初始化,不可以搞倒了。
比较重要的位如下:
RXIRQ/FFULL:选择中断源是接收就绪还是缓冲满。
PM:校验选择。
B/C:数据位宽度。
而其他位按照自己的需要设置即可。
2、模式寄存器2 UMR2n
图三 模式寄存器2
初始化时注意,先把模式寄存器指针清零,初始化完模式寄存器1后,才可以初始化此寄存器。
比较重要的位如下:
CM:四种模式选择。
SB:停止位个数。
其他按照需要设计即可。
3、状态寄存器USRn
提供各种错误的检测,包括FFULL,RXRDY,TXRDY,TEMP等等,该寄存器为只读。
4、时钟选择寄存器 UCSRn
可以选择内部时钟Fsys,或者用外部输入。也许很多朋友不知道Fsys是多少,我现在使用的MCF52235的Fsys是60M,如果有不确定的,可以使用高精度示波器测量TCLK引脚,这样示波器自己就会显示出来。
5、命令寄存器 UCRn
刚才提到了,这个是发动命令的寄存器,可以发送的命令太多了,就不一一写了。只写个最常用的,我们在初始化UART前首先要禁用收和发,初始化完允许收和发,其中禁用和允许都需要配置这个寄存器来完成。
6、接收缓冲 URBn
接收缓冲,不用多说了。
7、发送缓冲 UTBn
也不用多说。
8、输入变化寄存器 UIPCRn
可以检测总线上的变化。
9、辅助控制寄存器 UACRn
IEC位是输入使能控制。
10、中断状态和屏蔽寄存器UISRn/UIMRn
图四 UISRn/UIMRn
必须注意FFULL/RXRDY和TXRDY位,否则中断将无法工作。当然有个真值表来表示他们的配合使用,详细请见DS的450页,这里写起来不方便就不多写了。再强调一下,这个是重点,建议去读原版文档。
11、波特率寄存器 UBG1n/UBG2n
用来分频的,有个计算公式,在功能描述里面,唯一需要注意的就是,16位的寄存器分为高8位和低8位,你需要明白高和低分别怎么存储就可以了。其值这样确定,分频子=Fsys/32/BR,我使用BR=9600,你也可以选择其他的。
12、UOP1n/UOP0n和UIPn不说了,一般用不太到。
三、给出我自己所用程序代码和注释
宏定义:
#define RAM_BUFFER_SIZE 0xffu
#define UART_NUMBER 0u
#define SYSTEM_CLOCK1 60000ul /* system bus frequency in KHz */
#if UART_NUMBER==0
#define MCF_GPIO_PUXPAR MCF_GPIO_PUAPAR
#define MCF_GPIO_PUXPAR_RXD0_RXD0 MCF_GPIO_PUAPAR_RXD0_RXD0
#define MCF_GPIO_PUXPAR_TXD0_TXD0 MCF_GPIO_PUAPAR_TXD0_TXD0
#elif UART_NUMBER==1
#define MCF_GPIO_PUXPAR MCF_GPIO_PUBPAR
#define MCF_GPIO_PUXPAR_RXD0_RXD0 MCF_GPIO_PUBPAR_RXD1_RXD1
#define MCF_GPIO_PUXPAR_TXD0_TXD0 MCF_GPIO_PUBPAR_TXD1_TXD1
#else
#define MCF_GPIO_PUXPAR MCF_GPIO_PUCPAR
#define MCF_GPIO_PUXPAR_RXD0_RXD0 MCF_GPIO_PUCPAR_RXD2_RXD2
#define MCF_GPIO_PUXPAR_TXD0_TXD0 MCF_GPIO_PUCPAR_TXD2_TXD2
#endif
初始化:
unsigned int uart_set_bps(unsigned long bps)
{
/* Calculate baud settings */
unsigned long d = ((SYSTEM_CLOCK1*125)/(bps*4));
if (d> 0xffff)
{
d="0xffff";
}
if (d <2)
{
d="2";
}
bps_divider_used=(unsigned int)d;
MCF_UART_UBG1(UART_NUMBER) = (unsigned char)(d >> 8);
MCF_UART_UBG2(UART_NUMBER) = (unsigned char)d;
return 1;//(uart_get_bps());
}
void uart_init1(unsigned long bps, unsigned char stp, unsigned char par, unsigned char ndata)
{
unsigned char umr1=0, umr2=0;
/* Init GPIO pins. */
//MCF_GPIO_PUXPAR = MCF_GPIO_PUXPAR_RXD0_RXD0 | MCF_GPIO_PUXPAR_TXD0_TXD0;
MCF_GPIO_PUXPAR=0b01010101;
/* Disable receiver and transmitter */
MCF_UART_UCR(0) = MCF_UART_UCR_TX_DISABLED | MCF_UART_UCR_RX_DISABLED;
/* Reset transmitter */
MCF_UART_UCR(0) = MCF_UART_UCR_RESET_TX;
/* and receiver */
MCF_UART_UCR(0) = MCF_UART_UCR_RESET_RX;
/* Reset Mode Register */
MCF_UART_UCR(0) = MCF_UART_UCR_RESET_MR;
switch(par)
{
default:
case 0: /* no parity */
umr1 |= MCF_UART_UMR_PM_NONE;
break;
case 1: /* odd parity */
umr1 |= MCF_UART_UMR_PM_ODD;
break;
case 2: /* even parity */
break;
}
switch(ndata)
{
case 5:
break;
case 6:
umr1 |= MCF_UART_UMR_BC_6;
break;
case 7:
umr1 |= MCF_UART_UMR_BC_7;
break;
case 8:
default:
umr1 |= MCF_UART_UMR_BC_8;
break;
}
switch(stp)
{
default:
case 1:
umr2 |= MCF_UART_UMR_SB_STOP_BITS_1;
break;
case 2:
umr2 |= MCF_UART_UMR_SB_STOP_BITS_15;
break;
case 3:
umr2 |= MCF_UART_UMR_SB_STOP_BITS_2;
}
/* Set line coding. */
/* Set Rx and Tx baud by SYSTEM CLOCK */
MCF_UART_UCSR(0) = (0|MCF_UART_UCSR_RCS_SYS_CLK | MCF_UART_UCSR_TCS_SYS_CLK);
MCF_UART_UIMR(0) = (0 |MCF_UART_UISR_FFULL_RXRDY);//| MCF_UART_UISR_TXRDY );//0b00000011;
MCF_INTC0_IMRL &= ~(0
| MCF_INTC_IMRL_INT_MASK13
| MCF_INTC_IMRL_MASKALL);
MCF_INTC0_ICR13 = 0b00011011;
//MCF_INTC0_ICR14 = 0b00011011;
//MCF_INTC0_ICR15 = 0b00011011;
MCF_UART0_UACR = 0;
MCF_UART0_UMR1 = 0b01010011;//umr1;
MCF_UART0_UMR2 = umr2;//0b00000111;//umr2;
uart_set_bps(bps);
/* Enable receiver and transmitter */
MCF_UART_UCR(0) =(0|MCF_UART_UCR_TX_ENABLED | MCF_UART_UCR_RX_ENABLED);
}//调用 uart_init1(9600, 1, 'n', 8);
接收:
unsigned int uart_rx1(void)
{
if (MCF_UART_USR(0) & MCF_UART_USR_RXRDY)
{
unsigned int c="MCF"_UART_URB(0);
//printf(c);
return(c);
}
return(1<<8);
}
发送:
void UART_Putch()
{
while (!(MCF_UART_USR(0) & MCF_UART_USR_TXRDY))
;
MCF_UART_UTB(0) = 101;//uart_rx1();//101;//uart_rx1();//102;
}
好,这样本文就完成了。另外说一句,这些代码我试过,绝对好用的,当然我是用CW 6.4做的,如果你拷贝过去,发现不正常,那么请检查你自己的程序是否有问题。如果不分任何原因就来瞎捣乱的,将删除评论并且投诉,最终封IP。