飞思卡尔单片机SCI通信程序讲义.docx
《飞思卡尔单片机SCI通信程序讲义.docx》由会员分享,可在线阅读,更多相关《飞思卡尔单片机SCI通信程序讲义.docx(17页珍藏版)》请在冰豆网上搜索。
![飞思卡尔单片机SCI通信程序讲义.docx](https://file1.bdocx.com/fileroot1/2022-11/28/1411bb40-b43a-4a4b-bae6-3f1db261c63d/1411bb40-b43a-4a4b-bae6-3f1db261c63d1.gif)
飞思卡尔单片机SCI通信程序讲义
SCI通信
一、飞思卡尔单片机DZ60SCI通信
(一)查询发送
#include/*forEnableInterruptsmacro*/
#include"derivative.h"/*includeperipheraldeclarations*/
#defineLED_D1PTDD_PTDD0
#defineLED_D1_DIRPTDDD_PTDDD0
#defineLED_ON0
#defineLED_OFF1
unsignedcharSCANF_SEND_STRINGS[]="HELLOMCUWORLD";
unsignedchar*pSendString=SCANF_SEND_STRINGS;
/*************************************************************/
/*初始化总线时钟PEE模式*/
/*外部晶振频率为4MHz,总线频率16MHz*/
/*************************************************************/
voidINIT_MCG(void)
{
MCGC2=0x36;
while(!
MCGSC_OSCINIT);
MCGC1=0xb8;
while(MCGSC_IREFST);
while(MCGSC_CLKST!
=0b10);
MCGC2_LP=1;
MCGC1=0x90;
MCGC3=0x48;
MCGC2_LP=0;
while(!
MCGSC_PLLST);
while(!
MCGSC_LOCK);
MCGC1=0x10;
while(MCGSC_CLKST!
=0b11);
}
voiddelay(void)
{
unsignedinti;
unsignedintj;
for(i=0;i<100;i++)
for(j=0;j<4000;j++);
}
voidmain(void)
{
DisableInterrupts;
SOPT1=0;
INIT_MCG();
EnableInterrupts;/*enableinterrupts*/
/*includeyourcodehere*/
LED_D1_DIR=1;
LED_D1=LED_OFF;
//以下为设置波特率,以及初始化SCI1控制寄存器
SCI1BDH=0X00;
SCI1BDL=0X68;//波特率设置为9600
SCI1C1=0x00;//设置SCI1为正常模式,八位数据位,无奇偶校验
SCI1C2=0x08;//允许发送数据,禁止中断功能
while
(1)
{
while((*pSendString)!
='\0')
{
while(!
SCI1S1_TDRE);//SCI1S1_TDRE为1表示发送数据缓冲器为空
SCI1D=*pSendString;
pSendString++;
LED_D1=~LED_D1;;//每发送一个字节,闪烁一次LED灯
delay();
}
}
for(;;){
__RESET_WATCHDOG();/*feedsthedog*/
}/*loopforever*/
/*pleasemakesurethatyouneverleavemain*/
(二)中断发送
#include/*forEnableInterruptsmacro*/
#include"derivative.h"/*includeperipheraldeclarations*/
#defineLED_D1PTDD_PTDD0
#defineLED_D1_DIRPTDDD_PTDDD0
#defineLED_ON0
#defineLED_OFF1
unsignedcharSCANF_SEND_STRINGS[]="HELLOMCUWORLD";
unsignedchar*pSendString=SCANF_SEND_STRINGS;
/*************************************************************/
/*初始化总线时钟PEE模式*/
/*外部晶振频率为4MHz,总线频率16MHz*/
/*************************************************************/
voidINIT_MCG(void)
{
MCGC2=0x36;
while(!
MCGSC_OSCINIT);
MCGC1=0xb8;
while(MCGSC_IREFST);
while(MCGSC_CLKST!
=0b10);
MCGC2_LP=1;
MCGC1=0x90;
MCGC3=0x48;
MCGC2_LP=0;
while(!
MCGSC_PLLST);
while(!
MCGSC_LOCK);
MCGC1=0x10;
while(MCGSC_CLKST!
=0b11);
}
voiddelay(void)
{
unsignedinti;
unsignedintj;
for(i=0;i<100;i++)
for(j=0;j<4000;j++);
}
voidmain(void){
DisableInterrupts;
SOPT1=0;
INIT_MCG();
EnableInterrupts;/*enableinterrupts*/
/*includeyourcodehere*/
LED_D1_DIR=1;
LED_D1=LED_OFF;
//以下为设置波特率,以及初始化SCI1控制寄存器
SCI1BDH=0X00;
SCI1BDL=0X68;//波特率设置为9600
SCI1C1=0x00;//设置SCI1为正常模式,八位数据位,无奇偶校验
SCI1C2=0x88;//TIE=1(bit7)启动TDRE中断,发送中断使能
//手册指出,如果设置了发送中断使能TIE位,每当TDRE=1时都请求硬件中断
//TE=1(bit3)发送器打开
while
(1);
for(;;){
__RESET_WATCHDOG();/*feedsthedog*/
}/*loopforever*/
/*pleasemakesurethatyouneverleavemain*/
}
/*************************************************************/
/*SCI1中断向量函数*/
/*向量编号为18,中断来源TDRE,TC*/
/*************************************************************/
interrupt18voidSCI1_SEND(void)
{
while(*pSendString!
='\0')
{
while(!
SCI1S1_TDRE);
SCI1D=*pSendString;
pSendString++;
LED_D1=~LED_D1;
//delay();
}
(三)查询接收
#include/*forEnableInterruptsmacro*/
#include"derivative.h"/*includeperipheraldeclarations*/
//整个功能:
PC-单片机-PC,PC串口发数据-单片机串口接收数据-单片机将接收到的数据发送回给PC
#defineLED_D1PTDD_PTDD0
#defineLED_D1_DIRPTDDD_PTDDD0
#defineLED_ON0
#defineLED_OFF1
unsignedcharSCANF_SEND_STRINGS[]="HELLOMCUWORLD";
unsignedchar*pSendString=SCANF_SEND_STRINGS;
unsignedcharReceiveString;
/*************************************************************/
/*初始化总线时钟PEE模式*/
/*外部晶振频率为4MHz,总线频率16MHz*/
/*************************************************************/
voidINIT_MCG(void)
{
MCGC2=0x36;
while(!
MCGSC_OSCINIT);
MCGC1=0xb8;
while(MCGSC_IREFST);
while(MCGSC_CLKST!
=0b10);
MCGC2_LP=1;
MCGC1=0x90;
MCGC3=0x48;
MCGC2_LP=0;
while(!
MCGSC_PLLST);
while(!
MCGSC_LOCK);
MCGC1=0x10;
while(MCGSC_CLKST!
=0b11);
}
//延时函数
voiddelay(void)
{
unsignedinti;
unsignedintj;
for(i=0;i<100;i++)
for(j=0;j<4000;j++);
}
voidmain(void)
{
DisableInterrupts;
SOPT1=0;
INIT_MCG();
EnableInterrupts;/*enableinterrupts*/
/*includeyourcodehere*/
LED_D1_DIR=1;
LED_D1=LED_OFF;
//以下为设置波特率,以及初始化SCI1控制寄存器
SCI1BDH=0X00;
SCI1BDL=0X68;//波特率设置为9600
SCI1C1=0x00;//设置SCI1为正常模式,八位数据位,无奇偶校验
SCI1C2=0x0C;//RE=1(bit2)接收器打开
//TE=1(bit3)发送器打开
while
(1)
{
while(!
SCI1S1_RDRF);//SCI1S1_RDRF=1时,表示接收数据寄存器满,可以取出数据
SCI1S1_RDRF=0;//清除SCI1S1_RDRF
ReceiveString=SCI1D;//将接收寄存器中的数据保存至ReceiveString
//LED_D1=~LED_D1;
//delay();
while(!
SCI1S1_TDRE);//SCI1S1_TDRE=1时,发送数据寄存器(缓存区)空,可以发送数据
SCI1D=ReceiveString;//将接收到的数据,放至发送数据寄存器(缓存区),发送
//LED_D1=~LED_D1;
//delay();
}
for(;;){
__RESET_WATCHDOG();/*feedsthedog*/
}/*loopforever*/
/*pleasemakesurethatyouneverleavemain*/
}
程序改成下面语句,上位机串口发大数据不死机,但可能丢数据。
while
(1)
{
/*while(!
SCI1S1_RDRF);//SCI1S1_RDRF=1时,表示接收数据寄存器满,可以取出数据
SCI1S1_RDRF=0;//清除SCI1S1_RDRF
ReceiveString=SCI1D;//将接收寄存器中的数据保存至ReceiveString
while(!
SCI1S1_TDRE);//SCI1S1_TDRE=1时,发送数据寄存器(缓存区)空,可以发送数据
SCI1D=ReceiveString;//将接收到的数据,放至发送数据寄存器(缓存区),发送
*/
if(SCI1S1_RDRF==1)
{
ReceiveString=SCI1D;
if(SCI1S1_TDRE==1)
{
SCI1D=ReceiveString;
}
}
(四)中断接收
#include/*forEnableInterruptsmacro*/
#include"derivative.h"/*includeperipheraldeclarations*/
#defineLED_D1PTDD_PTDD0
#defineLED_D1_DIRPTDDD_PTDDD0
#defineLED_ON0
#defineLED_OFF1
unsignedcharSCANF_SEND_STRINGS[]="HELLOMCUWORLD";
unsignedchar*pSendString=SCANF_SEND_STRINGS;
unsignedcharReceiveString;
/*************************************************************/
/*初始化总线时钟PEE模式*/
/*外部晶振频率为4MHz,总线频率16MHz*/
/*************************************************************/
voidINIT_MCG(void)
{
MCGC2=0x36;
while(!
MCGSC_OSCINIT);
MCGC1=0xb8;
while(MCGSC_IREFST);
while(MCGSC_CLKST!
=0b10);
MCGC2_LP=1;
MCGC1=0x90;
MCGC3=0x48;
MCGC2_LP=0;
while(!
MCGSC_PLLST);
while(!
MCGSC_LOCK);
MCGC1=0x10;
while(MCGSC_CLKST!
=0b11);
}
//延时函数
voiddelay(void)
{
unsignedinti;
unsignedintj;
for(i=0;i<100;i++)
for(j=0;j<4000;j++);
}
voidmain(void)
{
DisableInterrupts;
SOPT1=0;
INIT_MCG();
EnableInterrupts;/*enableinterrupts*/
/*includeyourcodehere*/
LED_D1_DIR=1;
LED_D1=LED_OFF;
//以下为设置波特率,以及初始化SCI1控制寄存器
SCI1BDH=0X00;
SCI1BDL=0X68;//波特率设置为9600
SCI1C1=0x00;//设置SCI1为正常模式,八位数据位,无奇偶校验
SCI1C2=0x2C;//RE=1(bit2)接收器打开
//TE=1(bit3)发送器打开
while
(1)
{
}
for(;;){
__RESET_WATCHDOG();/*feedsthedog*/
}/*loopforever*/
/*pleasemakesurethatyouneverleavemain*/
}
/*************************************************************/
/*SCI1中断向量接收函数*/
/*向量编号为17,中断来源RDRF等*/
/*************************************************************/
interrupt17voidSCI1_RECEIVE(void)
{
while(!
SCI1S1_RDRF);//SCI1S1_RDRF=1时,表示接收数据寄存器满,可以取出数据
ReceiveString=SCI1D;//将接收寄存器中的数据保存至ReceiveString
LED_D1=~LED_D1;
while(!
SCI1S1_TDRE);//SCI1S1_TDRE=1时,发送数据寄存器(缓存区)空,可以发送数据
SCI1D=ReceiveString;//将接收到的数据,放至发送数据寄存器(缓存区),发送
}
二、飞思卡尔单片机应用实验指导
实验二串口通信(SCI)实验
(一)实验目的:
1.进一步熟悉嵌入式开发系统环境、汇编、C语言、调试方式。
2.加强串口通信(SCI)基本原理及编程原理的理解。
3.理解C语言工程结构,掌握运用08C建立工程的方法。
4.分别运用查询方式、中断方式实现通信。
(二)实验要求:
1.仔细阅读本实验指导书。
2.复习有关的串行通信(SCI)的章节
3.熟悉AW60串行通信(SCI)的工作方法及编程。
4.根据实验内容要求编写好程序,为实验做充分地准备。
实验原理图如下:
(三)实验设备及其连接
1.PC机一台
2.飞思卡尔嵌入式实验开发系统一台
3.串行通信线一根
4.万用表一只
(四)实验内容
1.理解串行通信(SCI)原理。
2.运行与理解各子程序。
3.主程序运行课本的样例程序。
4.编制一个查询方式通信程序。
将字符通过SCI一个一个地发送,发送完一个字符后,控制接在PTB0~PTB7的8个LED灯显示被发送字符的ASCII码。
5.编制一个中断方式通信程序。
编程要求同上一条。
(五)编程提示
1.按照结构要求写好编程代码和注释。
2.计算波特率,SCInInit(SCI初始化子程序)设置SCI比特率寄存器(SCInBDH,SCInBDL),设置允许SCI、正常码输出、8位数据、无校验,即设置SCI控制寄存器1(SCIxC1)相应位,设置是否允许发送与接收、是中断接收还是查询接收,即设置SCI控制寄存器2(SCIxC2)相应位。
3.查询方式通信程序的主程序主体是一个死循环,循环体中是不断检测SCI是否发送完毕,即检测SCI状态寄存器1(SCIxS1)第七位是否为1,为1则将字符的ASCII码输出到接在PTB口的LED上,并延时一会。
4.中断方式通信程序的主程序也主体是一个死循环,但该循环体是一个空循环体,所有接收和发送数据程序代码放在中断程序中,这里没有检测代码,数据开始发送和接收的条件就是中断的条件。
(六)实验报告要求
1.小结AW60串行通信(SCI)的原理及编程,并画出其流程图和程序代码与硬件接线图。
2.小结中断方式和查询方式的编程方法,并画出其流程图和程序代码与硬件接线图。
3.回答下列问题
(1)串行SCI通信有哪些中断?
各在什么情况下发生,作用是什么?
(2)如何知道串行口TX发送了信号?
提示:
方法一,利用万用表在TX端发送0或者255持续0.5秒钟时的电压值。
方法二,在TX端发送0或255持续0.5秒钟的波形时的小灯变化。
(七)参考例程:
voidmain(void){
unsignedcharSerialBuff[]="Hello!
World!
";//初始化存放接收数据的数组
//1关总中断
DisableInterrupts;//禁止总中断
//2芯片初始化
MCUInit();
//3模块初始化
SCIInit();//串行口初始化
//4开放中断
EnableInterrupts;//开放总中断
SCISendN(13,SerialBuff);//串口发送“HelloWorld!
”
//5主循环
while
(1)
{
if
((SCI1S1&SCI1S1_RDRF_MASK)!
=0){
PTBD=SCI1D;
if((SCI1S1&SCI1S1_TDRE_MASK)!
=0)
SCI1D=PTBD;
}
else
PTBD=0x00;
}
}
voidMCUInit(void)
{
SOPT=0b01100000;//$70SystemOptionsRegister(writeonce)
ICGC2=0b00110000;//$30internalclockgeneration2
ICGC1=0b01111000;//$78internalclockgeneration1
//等待FLL稳定
while(!
ICGS1_LOCK);
PTBDD=0xff;
PTBD=0xff;
}
voidSCIInit()
{
unsignedintubgs,baud=9600;
unsignedcharsysclk=20;
//1.计算波特率并设置:
ubgs=fsys/(波特率*16)(其中fsys=sysclk*1000000)
ubgs=sysclk*(10000/(baud/100))/16;//理解参考上一行,此处便于CPU运算
SCI1BDH=(unsignedchar)((ubgs&0xFF00)>>8);
SCI1BDL=(unsignedchar)(ubgs&0x00FF);
//无校验,正常模式(开始信号+8位数据(先发最低位)+停止信号)
SCI1C1=0;
//允许发送,允许接收,查询方式收发
SCI1C2=(0
|SCI1C2_TE_MASK
|SCI1C2_RE_MASK);