SCI程序串行通信时MCU与外部设备之间进行通信的一种简单而有效的硬件方法。
无论用查询方式还是中断方式进行串行通信编程,在程序初始化时均必须对SCI进行初始化。
初始化主要包括波特率设置、通信格式的设置、发送接收数据方式的设置等。
对SCI进行初始化,需要设置如下几部分:(1)定义波特率一般选内部总线时钟为串行通信的时钟源。
通过设置SCI波特率寄存器SCI0BD的波特率选择位SBR[12:0],来选择合适的分频系数。
(2)写控制字到SCI控制寄存器1(SCI0CR1)设置是否允许SCI、数据长度、输出格式、选择唤醒方法、是否校验等。
(3)写控制字到SCI控制寄存器2(SCI0CR2)设置是否允许发送与接收、是中断接收还是查询接收等。
串行通信程序如下:/** write in “Init.h” **/#include <hidef.h> /* common defines and macros */#include "derivative.h" /* derivative-specific definitions *///void InitBusClk(void); //可以不使用锁相环void InitSci(void);/** write in “Init.c” **///初始化程序#include "Init.h"/*//------------初始化Bus Clock------------//void InitBusClk(void) {DisableInterrupts;CLKSEL=0X00; //PLLSEL 1 : Bus Clock=PLLCLK/2// 0 : Bus Clock=OSCCLK/2PLLCTL_PLLON=1; //开启PLLSYNR=0; //OSCCLK=16MHzREFDV=0X0F; //PLLCLK=2*OSCCLK*[(1+SYNR)/(1+REFDV]=32/16=2MHz while(!(CRGFLG_LOCK==1)); //直到LOCK=1,when PLL is ready,退出循环CLKSEL_PLLSEL=1; //PLLSEL 1 : Bus Clock=PLLCLK/2=2MHz/2=1MHz// 0 : Bus Clock=OSCCLK/2=16M/2=8MHz}*///---------------初始化SCI---------------//void InitSci(void){SCI0BD=4545; //设波特率为110//SCI baud rate = SCI module clock/(16*SCIBD)=Bus Clock/(16*SCIBD)// = 8MHz/(16*4545)=500kHz/4545=110bps//SCIBD : SBR12-SBR0,Value from 1 to 8191SCI0CR1=0;SCI0CR2=0X2C; // 0010 1100 RIE=1,TE=1,RE=1// RIE=1 RDRF and OR interrupt requests enabled// TE=1 Transmitter enabled// RE=1 Receiver enabled}/** write in “SCI.h” **///函数声明unsigned char SciRead();void SciWrite(byte);/** write in “SCI.c” **///串行通信程序#include "Init.h"#include "SCI.h"//---------------读SCI数据---------------//unsigned char SciRead(){if(SCI0SR1_RDRF==1){//数据从移位寄存器传送到SCI数据寄存器SCIDRL//SCI0SR1_RDRF==1表明数据寄存器SCI0DRL为满,可以接收新的数据SCI0SR1_RDRF=1; //读取SCI数据寄存器会将RDRF清除,重新置位return SCI0DRL; //返回数据寄存器的数值}}//---------------写SCI数据---------------//void SciWrite(byte sci_value){while(!(SCI0SR1&0X80));//SCI0SR1_TDRE==1表明数据寄存器SCI0DRL为空,可以发送新的数据SCI0DRH=0;SCI0DRL=sci_value; //发送新的数据至数据寄存器SCI0DR}//---------------中断程序-----------------//#pragma CODE_SEG NON_BANKEDinterrupt 20 void Sci_Intrrupt(void){ //SCI的中断向量号为20byte text;DisableInterrupts; //关中断text=SciRead(); //接收数据寄存器SCI0DRL中的数据asm nop;asm nop;SciWrite(text); //发送数据至数据寄存器SCI0DRLDDRA=0XFF; //设A口为输出,用来显示是否执行中断,可以不用PORTA_PA6=!PORTA_PA6;EnableInterrupts; //开中断}#pragma CODE_SEG DEFAULT/** write in “main.c”” **/#include "Init.h"#include "SCI.h"void main(void) {/* put your own code here */_DISABLE_COP(); //关看门狗DisableInterrupts; //关中断//InitBusClk();InitSci();EnableInterrupts; //开中断for(;;) {// _FEED_COP(); /* feeds the dog */} /* loop forever *//* please make sure that you never leave main */}A/D转换应用实例要让ATD 开始转换工作,必须经过以下三个步骤:1.将ADPU 置1,使ATD 启动;2.按照要求对转换位数、扫描方式、采样时间、时钟频率及标志检查等方式进行设置;3.发出启动命令;如果上电默认状态即能满足工作要求,那么只要将ADPU 置1,然后通过控制寄存器发出转换命令,即可实现转换。
程序描述:由通道ATD0进行单通道A/D转换,转换值在B口显示。
程序如下:程序一:#include <hidef.h> /* common defines and macros */#include "derivative.h" /* derivative-specific definitions */byte ad_value; //AD转换结果void Delay(int i) { //延时程序int j;for(;i>0;i--)for(j=500;j>0;j--);}/***---------------初始化程序---------------***/void InitBusClk(void) {CLKSEL=0X80; //PLLSEL 1 : Bus Clock=PLLCLK/2// 0 : Bus Clock=OSCCLK/2PLLCTL_PLLON=1; //开启PLLSYNR=0;REFDV=0X03; //OSCCLK=16MHz//PLLCLK=2*OSCCLK*[(1+SYNR)/(1+REFDV]=32/4=8MHzwhile(!(CRGFLG_LOCK==1)); //直到LOCK=1,when PLL is ready,退出循环CLKSEL_PLLSEL=1;//PLLSEL 1 : Bus Clock=PLLCLK/2=8MHz/2=4MHz// 0 : Bus Clock=OSCCLK/2=16M/2=8MHz}void InitAD(void){ATD0CTL2 = 0XC0; // 1100 0000 启动A/D,快速清除标志位// 无等待模式,外部触发禁止(bit2=0),中断禁止(bit1=0)ATD0CTL3 = 0X0C;// 0 0001 1 00 转换序列为1 、FIFO模式启动,冻结模式下继续转换ATD0CTL4 = 0XE1; // 1 11 00001 8位精度,16AD采样时间// 总线(1+1)*2 = 4 分频,AD时钟= 1MHz ATD0CTL5 = 0X27;// 0 0 1 0 0 111 右对齐,无符号,连续转换,单通道, 起始通道ATD7// DJM DSGN SCAN MULT 0 CC CB CA// DJM :1-Right justified 0-Left justified// DSGN:1-Signed data 0-Unsigned data// SCAN:1-Continuous 0-Single conversion// CC CB CA : Analog Input Channel Select CodeATD0DIEN = 0X00; // 数字输入disabled}/***---------------主程序---------------***/void main(void) {/* put your own code here */_DISABLE_COP(); // 关看门狗InitBusClk();InitAD();DDRB=0XFF; // 设PORTB为输出口PORTB=0x00;EnableInterrupts; // 开放总中断for(;;) {while(!ATD0STAT2L_CCF7); //等待转换结束,退出循环ad_value=(byte)ATD0DR7H;//左对齐,右对齐时转换结果都先存储在ATD0DRxH,后存储在ATD0DRxL.Delay(200); //延时PORTB=ad_value;//PORTB输出AD转换结果,并用8个LED发光二极管显示//_FEED_COP(); /* feeds the dog */} /* loop forever *//* please make sure that you never leave main */}程序二:(用指针实现AD转换)#include <hidef.h> /* common defines and macros */#include "derivative.h" /* derivative-specific definitions */ byte AD_Value; //AD转换结果void Delay(int i) { //延时程序int j;for(;i>0;i--)for(j=500;j>0;j--);}/***---------------初始化程序---------------***/(初始化程序与上述相同)/***---------------读取AD转换结果---------------***/void AD_GetValue(word *AD_Value){*AD_Value=ATD0DR0;}void main(void) {/* put your own code here */_DISABLE_COP(); //关看门狗InitBusClk();InitAD();DDRB=0XFF; //设PORTB为输出口PORTB=0x00;EnableInterrupts;for(;;) {while(!ATD0STAT2L_CCF7); //等待转换结束,退出循环AD_GetValue(&AD_Value); //读取转换结果Delay(400);PORTB=AD_Value; //转换结果在B口显示_FEED_COP(); /* feeds the dog */} /* loop forever *//* please make sure that you never leave main */}程序三:(用中断实现AD转换)#include <hidef.h> /* common defines and macros */#include "derivative.h" /* derivative-specific definitions */#include <mc9s12xs128.h>byte AD_Data=0;//*void Delay(int i) {int j;for(;i>0;i--)for(j=500;j>0;j--);}//*//***---------------初始化程序---------------***/void InitBusClk(void) {CLKSEL=0X80; //PLLSEL 1 : Bus Clock=PLLCLK/2// 0 : Bus Clock=OSCCLK/2PLLCTL_PLLON=1; //开启PLLSYNR=0;REFDV=0X03; //OSCCLK=16MHz//PLLCLK=2*OSCCLK*[(1+SYNR)/(1+REFDV]=32/4=8MHz while(!(CRGFLG_LOCK==1)); //直到LOCK=1,when PLL is ready,退出循环CLKSEL_PLLSEL=1; //PLLSEL 1 : Bus Clock=PLLCLK/2=8MHz/2=4MHz// 0 : Bus Clock=OSCCLK/2=16M/2=8MHz}void InitAD(void){ATD0CTL2 = 0XC3;// 110 000 11 启动A/D,快速清除标志位,无等待模式,外部触发禁止(bit2=0) // 中断开放(bit1=1,bit0=1)// bit1 :ATD Sequence Complete Interrupt Enable// bit0 :ATD Sequence Complete Interrupt FlagATD0CTL3 = 0X0C;// 0 0001 1 00 转换序列为1 、FIFO模式启动,冻结模式下继续转换ATD0CTL4 = 0XE1; // 1 11 00001 8位精度,16AD采样时间// 总线(1+1)*2 = 4 分频,AD时钟= 1MATD0CTL5 = 0XA7;// 1010 0111 右对齐,无符号,连续转换,单通道, 起始通道ATD7ATD0DIEN = 0X00; // 数字输入disabled}/***---------------主程序---------------***/void main(void) {/* put your own code here */DisableInterrupts; //关中断InitBusClk();InitAD();DDRB=0XFF; //设B口为输出口PORTB=0X00;EnableInterrupts; //开中断for(;;){//while(!ATD0STAT2L_CCF7);PORTB=(byte)AD_Data; //B口显示转换结构}}/***---------------中断服务程序---------------***/#pragma CODE_SEG NON_BANKEDvoid interrupt 22 IntAD(void){ // AD转换的中断向量号为33 DisableInterrupts; //关中断//while(!ATD0STAT2L_CCF7);AD_Data=ATD0DR0H; //读取AD转换结果EnableInterrupts; //开中断}#pragma CODE_SEG DEFAULTPWM例程//---------------------------------------------------------------------------------------------------////功能说明:MC9S12XS128--PWM例程//使用说明:实现通道0(PTP0)输出频率为1Hz,占空比为50%的方波,可以用发光二极管显示,每秒钟放光二极管亮一次//--------------------------------------------------------------------------------------------------//#include <hidef.h> /* common defines and macros */#include "derivative.h" /* derivative-specific definitions */void Delay(int i){int j ;for(;i>0;i--)for(j=500;j>0;j--);}void InitPWM(void){PWME =0x00; //clear PWM Enable register 关闭PWM输出PWMPOL = 0XFF; //初始极性高电平PWMCAE =0x00; // left allign 左对齐//PWMCTL = 0x50; // 0101 0000 CON01 CON45PWMCLK = 0x01; // 0000 0001 con0 uses Clock SA// SA Clock A is the clock source for PWM channel 0// SA Clock SA is the clock source for PWM channel 1// SA Clock B is the clock source for PWM channel 2// SA Clock B is the clock source for PWM channel 3// SA Clock A is the clock source for PWM channel 4// SA Clock A is the clock source for PWM channel 5// SA Clock B is the clock source for PWM channel 6// SA Clock B is the clock source for PWM channel 7PWMPRCLK=0x07;// 0000 0111 时钟A 128分频clockA=bus colck/128=8MHz/128=1/16 MHzPWMSCLA=0XFA;// 1111 1010 时钟SA为1/16MHz/(250*2)=1/8000MHz=1/8kHz=1000/8Hz=125HzPWMPER0=125; // Period = 1s *** (0.008)*125=1s *** PWMDTY0=60;PWME = 0x01; // 0000 0001 开启通道0的PWM 输出}void main(void) {/* put your own code here */InitPWM();EnableInterrupts;for(;;) {_FEED_COP(); /* feeds the dog */} /* loop forever *//* please make sure that you never leave main */}。