设计串口通信程序,主要是掌握四个寄存器,设置好初始化。本着有用的原则,我们不对所有的寄存器含义进行说明,只介绍用得着的。
硬件电路: 将MPU与RS232相连
寄存器:
SCDR:SCI数据寄存器 所在地址: @0x00000018
功能:
一个八位的寄存器,当微控制器向外发送时,将要发送的数据放入SCDR,当要接收外来数据时,外来数据会被暂存入SCDR,微控制器从SCDR中取出此数据,可以把SCDR看成一个交换数据的缓冲区。
主要用法:
byte data;
data=SCDR;//将值取出
SCDR=data;//将值放入
SCC1:SCI控制寄存器1所在地址: @0x00000013
功能速查表:(红色代表比较重要的)
地址 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
ENSCI 串口使能 |
M 字符长度 |
PEN 奇偶校验使能 |
PTY 奇偶校验方式 |
|||||
置1 |
SCI允许 |
9位 |
允许 |
寄校验 |
||||
置0 |
SCI禁止 |
8位 |
禁止 |
偶校验 |
||||
默认 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
虽然表中有的放矢的删去了很多不常用的位功能,但是还是很难记,怎么办呢?其实,每一位的含义在头文件中都有详细地说明,学会阅读头文件,必将达到好学好记,事半功倍的效果。因此,作为本资料的最后一篇文章,此文带领你阅读头文件。以便对以后的工作有一个交待,实现可持续发展。
头文件定义:
/*** SCC1 - SCI 寄存器1 ***/
typedef union {
byte Byte;
struct {
byte PTY:1;/* Parity Bit */
byte PEN:1;/* Parity Enable Bit */
byte ILTY:1;/* Idle Line Type Bit */
byte WAKE:1;/* Wakeup Condition Bit */
byte M:1;/* Mode (Character Length) Bit */
byte TXINV:1;/* Transmit Inversion Bit */
byte ENSCI:1;/* Enable SCI Bit */
byte LOOPS:1;/* Loop Mode Select Bit */
} Bits;
} SCC1STR;
extern volatile SCC1STR _SCC1 @0x00000013;
你会发现,它从第0位开始,到第七位,每一位名称和表中一致,每一位含义用注释给出。
最后一句说明了SCC1使这种结构的一个实际的变量,它叫SCC1, 地址位于 @0x00000013,以后我们就用SCC1代表这个寄存器。
主要用法:
由于SCC1支持位赋值,所以可以对单个位进行操作。
请先不要看注释,对照表格和头文件讲出含义,然后和注释对照。
(1) SCC1_ENSCI=1; // 开启SCI传输
(2) SCC1=0x53;//八位含义是 0,1使能SCI,0,1九位数据,00,1使能校验,1寄校验
SCC2:SCI控制寄存器2所在地址@0x00000014
功能速查表:
地址 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
SCITE发送中断使能 |
|
SCITE接收中断使能 |
TE发送使能 |
RE接收使能 |
SBK 发送中止位 |
|||
置1 |
允许 |
|
允许 |
允许 |
允许 |
发送 |
||
置0 |
禁止 |
|
禁止 |
禁止 |
禁止 |
不发送 |
||
默认 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
头文件定义:
/*** SCC2 - SCI控制寄存器2 ***/
typedef union {
byte Byte;
struct {
byte SBK:1;/* Send Break Bit */
byte RWU:1;/* Receiver Wakeup Bit */
byte RE:1;/* Receiver Enable Bit */
byte TE:1;/* Transmitter Enable Bit */
byte ILIE:1;/* Idle Line Interrupt Enable Bit */
byte SCRIE:1;/* SCI Receive Interrupt Enable Bit */
byte TCIE:1;/* Transmission Complete Interrupt Enable Bit */
byte SCTIE:1;/* SCI Transmit Interrupt Enable Bit */
} Bits;
} SCC2STR;
extern volatile SCC2STR _SCC2 @0x00000014;
主要用法:
(1) SCC2=0xac;//八位含义:1发送中断使能,0,1接收中断使能,0,1发送使能1接收使能,00,这种初始化方式主要用于中断方式传输
(2) SCC2_TE=1;SCC_RE=1;//使能发送和接收器,用于非中断方式
SCC3:SCI控制寄存器2所在地址@0x00000014
功能:主要用于线路状态检测。简单的实现一般用不到。有兴趣的参考头文件定义
/*** SCC3 - SCI 控制寄存器3 ***/
typedef union {
byte Byte;
struct {
byte PEIE:1;/* Receiver Parity Error Interrupt Enable Bit */
byte FEIE:1;/* Receiver Framing Error Interrupt Enable Bit */
byte NEIE:1;/* Receiver Noise Error Interrupt Enable Bit */
byte ORIE:1;/* Receiver Overrun Interrupt Enable Bit */
byte:1;
byte:1;
byte T8:1;/* Transmitted Bit 8 */
byte R8:1;/* Received Bit 8 */
} Bits;
} SCC3STR;
extern volatile SCC3STR _SCC3 @0x00000015;
SCS1状态寄存器1所在地址@0x00000016
功能速查表:
地址 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
SCTE发送器空 |
SCRF接收器满 |
|||||||
置1 |
空,可以放数据 |
满,可以取数据 |
||||||
置0 |
满 |
没数据 |
||||||
默认 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
头文件定义:
/*** SCS1 - SCI状态寄存器1 ***/
typedef union {
byte Byte;
struct {
byte PE:1;/* Receiver Parity Error Bit */
byte FE:1;/* Receiver Framing Error Bit */
byte NF:1;/* Receiver Noise Flag Bit */
byte OR:1;/* Receiver Overrun Bit */
byte IDLE:1;/* Receiver Idle Bit */
byte SCRF:1;/* SCI Receiver Full Bit */
byte TC:1;/* Transmission Complete Bit */
byte SCTE:1;/* SCI Transmitter Empty Bit */
} Bits;
} SCS1STR;
extern volatile SCS1STR _SCS1 @0x00000016;
主要用法:
if(SCS1_SCTE==1) SCDR=data;//如果发送器空,则把数(data)放进去
if(SCS1_SCRF==1) data=SCDR;//如果接收器满,则把数取出来
SCBR:SCI波特率寄存器所在地址@0x00000019
5,4两位确定了预分频,2,1,0三位确定了波特率分频,两者通过公式
波特率=SCI时钟频率/(64*预分频*波特率分频)
计算出波特率。由此,可作出下列常用波特率设置表,此表只列出常见的波特率
SCP1 |
SCP0 |
预分频 |
SCR2 |
SCR1 |
SCR0 |
波特率分频 |
波特率 |
0 |
0 |
1 |
0 |
0 |
1 |
1 |
38400 |
0 |
0 |
1 |
0 |
1 |
0 |
2 |
19200 |
0 |
0 |
1 |
0 |
1 |
1 |
8 |
9600 |
0 |
0 |
1 |
1 |
0 |
0 |
16 |
4800 |
0 |
0 |
1 |
1 |
0 |
1 |
32 |
2400 |
0 |
0 |
1 |
1 |
1 |
0 |
64 |
1200 |
1 |
0 |
4 |
0 |
0 |
0 |
1 |
19200 |
1 |
0 |
4 |
0 |
1 |
0 |
4 |
4800 |
1 |
0 |
4 |
0 |
1 |
1 |
8 |
2400 |
1 |
0 |
4 |
1 |
0 |
1 |
32 |
600 |
1 |
0 |
4 |
1 |
1 |
1 |
128 |
300 |
头文件定义:
/*** SCBR - SCI Baud Rate Register ***/
typedef union {
byte Byte;
struct {
byte SCR0:1;/* SCI Baud Rate Select Bit 0 */
byte SCR1:1;/* SCI Baud Rate Select Bit 1 */
byte SCR2:1;/* SCI Baud Rate Select Bit 2 */
byte:1;
byte SCP0:1;/* SCI Baud Rate Prescaler Bit 0 */
byte SCP1:1;/* SCI Baud Rate Prescaler Bit 1 */
byte:1;
byte:1;
} Bits;
struct {
byte SCR:3;
byte:1;
byte SCP:2;
byte:1;
byte:1;
} MergedBits;
} SCBRSTR;
extern volatile SCBRSTR _SCBR @0x00000019;
主要用法:
SCBR=0x04;// 波特率为4800
好了,也许已经被一大堆寄存器搞晕了,或者勉强读完第一个表格,浏览完第二个表格,就看到这里了,通过程序学寄存器,是最好的方式,毕竟我们最终都是用程序来实现。下面,我们一起动手自己做两个小程序,一个是查询方式串口传输的最简形式,一个是中断方式传输的最简形式,中断方式时,用13号中断向量代表接收中断,14号代表发送中断。分别调用不同的中断服务程序。之所以研究最简方式,是为了避免与一堆无关的知识点混淆,提取出精华。(中断就是让CPU停下当前的工作,转向中断服务程序处理中断任务。如果仍不懂什么是中断的话,强烈建议去寻找有关文档)
串口传输最简实现:
程序的任务:把收到的字符发回去
查询方式:
查询方式串口通信几步走:
(1) 设置CONFIG1,CONFIG2等,其作用与本文无关,不进行讨论
(2) 根据波特率,进行查表,设置SCBR
(3) 开启SCI传输。确定是否校验,从而设置SCC1
(4) 发送器,接收器使能,即设置SCC2
(5) 进入一个死循环
(6) 循环中检测,如果接收器满,就把数据从接收器取出来。如果发送器空,就把数据回送到发送器,如果发送器有数据,就等待;
好了,现在我们可以下笔了。
#include
#include
intdata;
void main(void) {
CONFIG1=0x01;//step1
SCBR_SCR1=1;//step2
SCBR_SCR0=1;
SCC1_ENSCI=1;//step3
SCC2_TE=1;//step4
SCC2_RE=1;
for(;;){//step5
if (SCS1_SCRF==1){ //step6
data=SCDR;
while(SCS1_SCTE==0);
SCDR=data;
}
}
}
中断方式串口通讯几步走:和上边得很像
(1) 设置CONFIG
(2) 根据波特率,进行查表,设置SCBR
(3) 开启SCI传输。确定是否校验,从而设置SCC1
(4) 发送器,接收器使能,接收中断使能,即设置SCC2
(5) 开中断。
(6) 主程序进入一个死循环。
(7) 定义一个接收中断服务程序,用于处理接收字符,接收完毕开启发送中断
(8) 定义一个发送中断服务程序,用于发送,把接收到的字符发出去
思路理清,代码自然就出来了。
#include
#include
int j;
void main(void) {
CONFIG1=0x01;//step1
SCBR_SCR1=1;//step2
SCBR_SCR0=1;
SCC1_ENSCI=1;//step3
SCC2=0b000101100;//step4
EnableInterrupts;//step5
for(;;){//step6
}
}
interrupt 13 void Rx(void){
j=SCDR;
while(SCS1_SCTE==0);
SCC2_SCTIE=1;//step7
}
interrupt 14 void Tx(void){
SCDR=j;
SCC2_SCTIE=0;//step8
}
好了,对MC68HC08微控制器的理解是不是加深了呢,其实它的工作很像可编程控制器,设置好工作方式,就能按我们的需求工作了。