Made By CreativeSoft Ver 1.0
设计串口通信程序,主要是掌握四个寄存器,设置好初始化。本着有用的原则,我们不对所有的寄存器含义进行说明,只介绍用得着的。突出重点,有点像考试提纲
硬件电路: 将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
地址 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
0 | 0 | SCP1 | SCP2 | 0 | SCR2 | SCR1 | SCR0 | ||
置1 | 联合作用 | 联合作用 | |||||||
置0 | |||||||||
默认 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
波特率=SCI时钟频率/(*预分频*波特率分频)
计算出波特率。由此,可作出下列常用波特率设置表,此表只列出常见的波特率
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 | 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 int data; 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微控制器的理解是不是加深了呢,其实它的工作很像可编程控制器,设置好工作方式,就能按我们的需求工作了。 参考资料:M68HC08单片机原理及c语言开发实例 常越 北京航空航天大学出版社 本文代码在code warrior 3.0 for 08平台下在BMTC实验室的MC68HC908GP32微控制器开发板通过