|
SCI程序
串行通信时MCU与外部设备之间进行通信的一种简单而有效的硬件方法。
无论用查询方式还是中断方式进行串行通信编程,在程序初始化时均必须对SCI进行初始化。初始化主要包括波特率设置、通信格式的设置、发送接收数据方式的设置等。
对SCI进行初始化,需要设置如下几部分:
定义波特率
一般选内部总线时钟为串行通信的时钟源。通过设置SCI波特率寄存器SCI0BD的波特率选择位SBR[12:0],来选择合适的分频系数。
写控制字到SCI控制寄存器1(SCI0CR1)
设置是否允许SCI、数据长度、输出格式、选择唤醒方法、是否校验等。
写控制字到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/2
PLLCTL_PLLON=1; //开启PLL
SYNR=0; //OSCCLK=16MHz
REFDV=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 8191
SCI0CR1=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_BANKED
interrupt 20 void Sci_Intrrupt(void){ //SCI的中断向量号为20
byte text;
DisableInterrupts; //关中断
text=SciRead(); //接收数据寄存器SCI0DRL中的数据
asm nop;
asm nop;
SciWrite(text); //发送数据至数据寄存器SCI0DRL
DDRA=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/2
PLLCTL_PLLON=1; //开启PLL
SYNR=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 = 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 Code
ATD0DIEN = 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/2
PLLCTL_PLLON=1; //开启PLL
SYNR=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 Flag
ATD0CTL3 = 0X0C;
// 0 0001 1 00 转换序列为 1 、 FIFO模式启动,冻结模式下继续转换
ATD0CTL4 = 0XE1; // 1 11 00001 8位精度, 16AD采样时间
// 总线(1+1)*2 = 4 分频,AD时钟 = 1M
ATD0CTL5 = 0XA7;
// 1010 0111 右对齐,无符号,连续转换,单通道, 起始通道 ATD7
ATD0DIEN = 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_BANKED
void interrupt 22 IntAD(void){ // AD转换的中断向量号为33
DisableInterrupts; //关中断
//while(!ATD0STAT2L_CCF7);
AD_Data=ATD0DR0H; //读取AD转换结果
EnableInterrupts; //开中断
}
#pragma CODE_SEG DEFAULT
PWM例程
//---------------------------------------------------------------------------------------------------//
//功能说明: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 十进制80 CON01 CON45
PWMCLK = 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 7
PWMPRCLK=0x07;
// 0000 0111 时钟A 128分频 clockA=bus colck/128=8MHz/128=1/16 MHz
PWMSCLA=0XFA;
// 1111 1010 时钟SA为1/16MHz/(250*2)=1/8000MHz=1/8kHz=1000/8Hz=125Hz
PWMPER0=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 */
}
希望对你能起到帮助 |
|