控制/MCU
电子发烧友网:随着驾驶员对车内舒适度和便利性的要求在提高,汽车车身电子产品在保持具有竞争力价格的同时,还需要继续提供性能更高的半导体。飞思卡尔半导体目前开始扩大现已普及的16位S12微控制器(MCU)系列,以优化大量对成本敏感的汽车车身电子应用。先进的S12G器件设计针对应用需求,提供灵活的内存、封装和成本选项。MC9S12G系列是一个专注于低功耗、高性能、低引脚数量的高效汽车级16位微控制器产品。这个系列是桥连8位高端微机和16位高性能微机,像MC9S12XS系列。本文将详细介绍关于飞思卡尔MC9S12系列的芯片简介、MC9S12单片机最小系统硬件设计、典型程序应用、飞思卡尔XS128和G128两种单片机的主要区别等进行阐述。
飞思卡尔MC9S12G系列单片机中文简介
1.1介绍
MC9S12G系列是一个专注于低功耗、高性能、低引脚数量的高效汽车级16位微控制器产品。这个系列是桥连8位高端微机和16位高性能微机,像MC9S12XS系列。MC9S12G系列是为了满足通用汽车CAN或LIN/J2602通信应用。这些应用的典型例子包括body controllers, occupant detection, doormodules, seat controllers, RKE receivers, smart actuators, lighting modules, and smart junction boxes.
MC9S12G系列使用了许多MC9S12XS系列和MC9S12P系列里面的相同特性,包括在闪存(flash memory)上的纠错指令(ECC),一个快速A/D转换器(ADC)和一个为了改善电磁兼容性(EMC)性能的频率调制相位锁存循环(IPLL)。
MC9S12G系列是高效的对较低的程序存储器至16K。为了简化顾客使用它,特制了一个4字节可擦除扇区的EEPROM。
MC9S12G系列传送所有16位单片机的优势和效率,定位于低成本,低功耗,EMC,现行代码尺寸效率优势被现存8位和16位单片机系列的使用者所分享。像MC9S12XS系列,MC9S12G系列运行16位位宽的访问对所有的周期和存储器状态都不用等待。
MC9S12G系列可得到的封装有100-pin LQFP, 64-pin LQFP, 48-pinLQFP/QFN, 32-pin LQFP and 20-pin TSSOP,特别是对较少引脚的封装发挥出最大的功能。此外,在每个模块中可得到的I/O口,进一步的可用于中断的I/O口允许从停止或等待模式中唤醒。
1.2特点
这部分说明了MC9S12G系列的关键特性。
1.2.1MC9S12G系列比较
表1-1提供了MC9S12G系列不同型号特点的概要。这个微机系统提供了一个明确的功能范围信息。
飞思卡尔MC9S12G系列芯片引脚图
飞思卡尔MC9S12G系列芯片内部资源模块框图
表1-1 MC9S12G系列概述
并不是所有的外围设备都能够应用于所有封装类型
表1-2显示出了每个封装外围设备或外围信道的最大值。并不是所有的外围设备都能够同时使用。可使用的外围设备的最大值还受到表1-1中所选芯片的限制。
表1-2 每个封装可使用外围设备的最大值
1.2.2 芯片水平特点
在这个系列里面可应用的模块包括以下特点:
S12内核
高达240KB的片内在线可编程FLASH存储器防纠错闪存
高达4KB防纠错EEPROM
高达11KB片内SRAM
拥有内部滤波器的锁相环回路(IPLL)频率乘法器
4-16MHz振幅控制穿透振荡器
1MHz内部RC振荡器
定时单元(TIM)支持达到8通道(提供16位输入俘获,输出比较,计数,脉冲存储器功能)
多达8*8通道脉宽调节(PWM)模块
多达16通道,10位或12位分辨率逐次近似计算法模数转换器(ADC)
多达两个8位数模转换器(DAC)
多达一个5V模拟比较器(ACMP)
多达3个串行外围接口模块(SPI)
多达3个串行通信接口(SCI)模块(支持LIN通信)
多达一个多级控制局域网(MSCAN)模块(支持CAN2.0 A/B 协议)
在线片内稳压器(VREG)用于控制内部供给和内部电压
自动周期性中断(API)
固定电压基准精度参考ADC转换器
为汽车电子定造
飞思卡尔S12G系列是需要CAN(控制器区域网络)或LIN(本地互连网络)/SAE J2602通讯的汽车应用的理想之选,这些应用包括车身控制器、车门模块、乘客检测、空调、座椅控制器和照明模块。这款16位S12G系列基于业界公认的S12架构,提供更复杂的应用设计所需的处理功能,保留了代码的有效性,同时还利用了广泛的S12生态系统,而这则有助于减少内存占用和开发成本。
MC9S12G128/96和MC9S12GN32/16是MC9S12G系列在市场上最先推出的四款主要产品。
汽车车身电子市场正在开发各种新应用,该市场对不同类型的微控制器应用具有特定的要求,需要不同的功能集。飞思卡尔这款先进的16位产品系列,能够为客户带来可靠的16位MCU产品的高性能,并且以8位MCU产品的价格提供更多的功能,进而实现更大的价值。
成熟的工艺技术
可扩展S12G系列填补了高端8位MCU和高性能16位MCU之间的空白。它采用成熟、高性价比的0.18微米工艺,提供能在大量低端车身应用范围工作的选项。汽车设计人员能够在内存器大小的封装内向上、向下迁移,并且与整个S12G系列完全兼容。此外,该16位产品系列包括板载EEPROM等增值功能,帮助客户设计出更复杂、但仍然对用户友好的应用。
MC9S12G系列是经过优化的汽车级16位微控制器产品线,具有低成本、高性能、引脚数量少的显著特点。MC9S12G系列适合需要CAN或LIN/SAE J2602通信的一般汽车应用。
MC9S12G系列具有16位MCU的所有优点和性能,同时保留了飞思卡尔现有8位和16位MCU系列用户所享有的低成本、低功耗、电磁兼容性(EMC)以及代码效率等优势。
关于MC9S12G系列16位MCU的特性:
•总线频率为25MHz的S12 CPU内核提供业界公认的S12架构和处理能力,以解决更复杂的传统8位应用设计版本;
•高达240KB的片上闪存(包括纠错码(ECC))可用来存储代码,帮助减少板上闪存/ROM;
•高达4KB的EEPROM(包括ECC)提供的用户界面比以前几代产品的数据快闪更简单;
•采用多个可扩展CAN模块(支持CAN协议2.0A/B),专为支持CAN通信端口复杂的系统需求而设计;
•三个串行通信接口模块用于支持LIN通信,三个串行外设接口(SPI)模块可以提供更好的灵活性、更多的选项和优势,同时需要增加SCI/LIN或SPI通信端口;
•在外设和存储器中提供16位存取,无等待状态;
•闪存从16K到240K不等,封装从20TSSOP到100LQFP不等,提供灵活的嵌入式设计和最大的功能;
•每个模块不但提供I/O端口,而且还在I/O端口提供中断功能,允许从停止或等待模式中唤醒;
•高达11KB片上SRAM,提供更多存储单元;
•精密固定电压参考用于ADC转换;
• 1MHz内部振荡器;
•片上稳压器调节输入电源和所有内部电压。
复位及时钟—复位
上电复位
单片机自动检测VDD端的正跳变,启动自动工作。
外部复位
通过RESET引脚加一低电压,拉低超过一定时间
后可实现复位。
看门狗复位
帮助系统在软件跑飞后自动复位。
时钟监视器复位
利用内部的RC电路来保证时钟频率满足要求。
振荡器和时钟电路
EXTAL是外部时钟输入或石英振荡放大器的输入
XTAL是石英振荡放大器的输出
注:DG128可用串联振荡电路和并联振荡电路两种连接方式。
9S12X系列单片机只可用并联振荡电路。
时钟初始化寄存器-共5个
(1)锁相环控制寄存器(PLLCTL)
(2)时钟合成寄存器(SYNR)-低6位有效,有效值0~63。
(3)时钟分频寄存器(REFDV)-低4位有效,有效值0~15。
由锁相环来产生时钟频率的公式:
例如:选用16MHz的外部晶振,若将SYNR设为
2,REFDV设为1,通过公式计算可得
PLLCLK=48MHz。从而得到系统的总线频
率为24MHz。
PLL例子
CLKSEL=0x00; //禁止PLL
PLLCTL=0xe1; //PLL电路允许
SYNR=2;REFDV=1; //设置倍频参数
PLLCTL=0x60; //时钟监控禁止
while(0==(CRGFLG&0x08));//等待稳定
CLKSEL=0x80; //选择PLL作为时钟
//若晶振为16M,则PLLCLK=2*16*3/2=48MHz,则总线频率是24MHz
RTI程序举例
RTICTL = 0x7e;//4M/15*2^16 = 4Hz
CRGINT = 0x80;
// 中断使能
得到大约每秒4次的中断
MC9S12单片机最小系统硬件设计
——以MC9S12DG128为例
时钟电路给单片机提供一个外接的16MHz的石英晶振
串口的RS-232驱动电路可实现TTL电平到RS-232电平的转换
BDM口让用户可以通过BDM调试工具向单片机下载和调试程序
供电电路主要是由单片机提供+5V电源和电源滤波
复位电路是通过一个复位按键给单片机一个复位信号,调试过程中很有用。
单片机MC9S12G128应用程序(PWM_Timer_ADC……)
PWM应用程序
/*
程序实现功能:PP1口输出PWM方波
程序说明:通过改变duty和period ,从而控制PWM周期和占空比
duty cycle=duty/period
PWM frequency=1M/(2*period)(Fbus=24M,scla=24)
*/
#include 《hidef.h》 /* common defines and macros */
#include “derivative.h” /* derivative-specific definitions */
void SetBusClock_24MHZ(void);
void PWMDisable(byte channel);
void PWMEnable(byte channel);
void PWMSinglePortSetting(byte channel ,byte period ,byte duty) ;
void PWMsinglePortInitial(byte channel, byte clkab,byte clock, byte polarity,byte align) ;
void Service_WD(void);
void PWMGeneralInitial(byte prclk,byte scla,byte sclb,byte ctl);
void PWMConcatenateSetting(byte channel,word period,word duty);
void main(void)
{
/* put your own code here */
//总线时钟频率设置:24M
SetBusClock_24MHZ();
//对预分频时钟,分频时钟A,分频时钟B和控制寄存器的配置
//0分频 01级联
PWMGeneralInitial(0,24,0,0x10);
//PWM端口寄存器的配置
// 1通道 SA时钟 起始高电平 左对齐
PWMsinglePortInitial(1,0,1,1,0);
//PWM级联输出配置
//50HZ 占空比12.5%
PWMConcatenateSetting(1,10000,250);
//EnableInterrupts;
for(;;) {
_FEED_COP(); /* feeds the dog */
} /* loop forever */
/* please make sure that you never leave main */
}
//*********************************************
//函数名:PWMEnable
//函数功能:PWM单个端口使能
//函数参数:一个 byte 类型channel 代表PWM通道号
// 返回值:无
//********************************************
void PWMEnable(byte channel)
{
if(channel》7) channel=7;
PWME|=(1《《channel); //选择使能位
}
//**********************************************
//函数名称:PWMDisable
//函数功能:PWM单个端口禁止
//函数参数:一个byte类型 channel 代表PWM通道号
//返回值:无
//***********************************************
void PWMDisable(byte channel)
{
if(channel》7) channel=7;
PWME&=~(1《《channel); //选择禁止位
}
//函数功能:启动看门狗
void Service_WD(void)
{
CPMUARMCOP=0x55;
CPMUARMCOP=0xAA;
}
//函数功能:总线时钟设置
void SetBusClock_24MHZ(void)
{
CPMUOSC_OSCE=1; //enable osc
/*
时钟倍频:24MHz BusClock
48MHz VCO
48MHz PLL
*/
CPMUSYNR=0x00|0x05; //VCOFRQ[1:0],SYNDIV[5:0]
CPMUREFDIV=0x20|0x03;//REFFRQ[1:0],REFDIV[3:0]
CPMUPOSTDIV=0x00; //POSTDIV=0;
while(!CPMUFLG_LOCK)//等待VCO稳定
Service_WD(); //看门狗
CPMUCLKS_PLLSEL=1;
}
//*********************************************
//函数名称: PWMSinglePortSetting
//函数功能:实现PWM周期寄存器和占空比寄存器通道的单独输出
//函数参数:3个 byte类型
//参数1: channel代表了当前配置的PWM通道
//参数2: period 周期配置参数
/*
Left aligned output (CAEx = 0) PWMx Period = Channel Clock Period * PWMPERx
Center Aligned Output (CAEx = 1) PWMx Period = Channel Clock Period * (2 * PWMPERx)
*/
//参数3: duty 占空比配置参数
/*
Polarity = 0 (PPOL x =0) Duty Cycle = [(PWMPERx-PWMDTYx)/PWMPERx] * 100%
Polarity = 1 (PPOLx = 1) Duty Cycle = [PWMDTYx / PWMPERx] * 100%
*/
//返回值:无
//**********************************************
void PWMSinglePortSetting(byte channel ,byte period ,byte duty)
{
if(channel》7) channel=7;
PWMDisable(channel); //禁止该通道
switch(channel)
{
case 0:
PWMPER0=period; //设置周期寄存器
PWMDTY0=duty; //设置占空比寄存器
break;
case 1:
PWMPER1=period; //设置周期寄存器
PWMDTY1=duty; //设置占空比寄存器
case 2:
PWMPER2=period; //设置周期寄存器
PWMDTY2=duty; //设置占空比寄存器
break;
case 3:
PWMPER3=period; //设置周期寄存器
PWMDTY3=duty; //设置占空比寄存器
break;
case 4:
PWMPER4=period; //设置周期寄存器
PWMDTY4=duty; //设置占空比寄存器
break;
case 5:
PWMPER5=period; //设置周期寄存器
PWMDTY5=duty; //设置占空比寄存器
break;
case 6:
PWMPER6=period; //设置周期寄存器
PWMDTY6=duty; //设置占空比寄存器
break;
case 7:
PWMPER7=period; //设置周期寄存器
PWMDTY7=duty; //设置占空比寄存器
break;
default:break;
}
PWMEnable(channel);
}
//*********************************************
//函数名:PWMSinglePortInitial
//函数功能:PWM端口寄存器的配置
//函数参数:5个byte类型
//参数1:channel 代表了当前配置的PWM通道
//参数2:clkab 参数2,3决定了时钟源的选择
//参数3: clock
/*
PWM Channel 0,1,4,5
PCLKAB[0,1,4,5] PCLK[0,1,4,5] Clock Source Selection
0 0 Clock A
0 1 Clock SA
1 0 Clock B
1 1 Clock SB
PWM Channel 2,3,6,7
PCLKAB[2,3,6,7] PCLK[2,3,6,7] Clock Source Selection
0 0 Clock B
0 1 Clock SB
1 0 Clock A
1 1 Clock SA
*/
//参数4:polarity PWM极性选择
// 0 开始为低电平,周期计数开始为高电平
// 1 开始为高电平,周期计数开始为低电平
//参数5:align PWM对齐方式选择
// 0 输出左对齐
// 1 输出中心对齐
//返回值:无
//**********************************************
void PWMsinglePortInitial(byte channel, byte clkab,byte clock, byte polarity,byte align)
{
if(channel》7) channel=7;
//禁止该通道
PWMDisable(channel);
// PWM 时钟A/B 选择
if(clkab==0) PWMCLKAB&=~(1《《channel);
else PWMCLKAB|=(1《《channel);
// PWM 时钟选择寄存器设置
if(clock==0) PWMCLK&=~(1《《channel);
else PWMCLK|=(1《《channel);
//PWM 极性选择设置
if(polarity==0) PWMPOL&=~(1《《channel) ;
else PWMPOL|=(1《《channel);
//PWM 对齐方式设置
if(align==0) PWMCAE&=~(1《《channel);
else PWMCAE|=(1《《channel);
}
//**********************************************************
//函数名:PWMGeneralInitial
//函数功能:对预分频时钟,分频时钟A,分频时钟B和控制寄存器的配置
//函数参数:4个byte类型
//参数1 prclk
/*
Clock A or Clock B Prescaler Selects
PCKA/B2 PCKA/B1 PCKA/B0 Value of Clock A/B
0 0 0 Bus clock
0 0 1 Bus clock / 2
0 1 0 Bus clock / 4
0 1 1 Bus clock / 8
1 0 0 Bus clock / 16
1 0 1 Bus clock / 32
1 1 0 Bus clock / 64
1 1 1 Bus clock / 128
*/
//参数2: scla
// Clock SA = Clock A / (2 * PWMSCLA)
//参数3: sclb
// Clock SB = Clock B / (2 * PWMSCLB)
//参数4: ctl
/*
control[CON67,CON45,CON23,CON01,PSWAI,PFRZ]
PWM级联控制寄存器 CON67,CON45,CON23,CON01
0 单独一个通道
1 两个通道级联
PSWAI 0 等待模式禁止时钟输入
1 等待模式允许时钟输入
PFRZ 0 冻结模式允许PWM时钟输入
1 冻结模式禁止PWM时钟输入
//返回值:无
*/
//**************************************************************
void PWMGeneralInitial(byte prclk,byte scla,byte sclb,byte ctl)
{
//禁止所有的PWM通道
PWME=0x00;
//设置预分频参数
PWMPRCLK=prclk;
//设置A分频参数
PWMSCLA=scla;
//设置B分频参数
PWMSCLB=sclb;
//级联配置
PWMCTL=ctl;
}
//***********************************************************
//函数名称:PWMConcatenateSetting
//函数功能:PWM级联输出配置
//函数参数:1个byte类型,2个word类型
//参数1: channel代表了当前配置的PWM通道
//参数2: period 周期配置参数
/*
Left aligned output (CAEx = 0) PWMx Period = Channel Clock Period * PWMPERx
Center Aligned Output (CAEx = 1) PWMx Period = Channel Clock Period * (2 * PWMPERx)
*/
//参数3: duty 占空比配置参数
/*
Polarity = 0 (PPOL x =0) Duty Cycle = [(PWMPERx-PWMDTYx)/PWMPERx] * 100%
Polarity = 1 (PPOLx = 1) Duty Cycle = [PWMDTYx / PWMPERx] * 100%
*/
//返回值:无
//**************************************************************
void PWMConcatenateSetting(byte channel,word period,word duty)
{
if(channel》7) channel=7;
switch(channel)
{
case 0:
case 1:PWMDisable(0); //禁止通道0
PWMDisable(1); //禁止通道1
PWMPER01=period; //设置周期寄存器
PWMDTY01=duty; //设置占空比寄存器
PWMEnable(0); //使能通道0;
PWMEnable(1); //使能通道1;
break;
case 2:
case 3:PWMDisable(2); //禁止通道2
PWMDisable(3); //禁止通道3
PWMPER23=period; //设置周期寄存器
PWMDTY23=duty; //设置占空比寄存器
PWMEnable(2); //使能通道2;
PWMEnable(3); //使能通道3;
break;
case 4:
case 5:PWMDisable(4); //禁止通道4
PWMDisable(5); //禁止通道5
PWMPER45=period; //设置周期寄存器
PWMDTY45=duty; //设置占空比寄存器
PWMEnable(4); //使能通道4;
PWMEnable(5); //使能通道5;
break;
case 6:
case 7:PWMDisable(6); //禁止通道6
PWMDisable(7); //禁止通道7
PWMPER67=period; //设置周期寄存器
PWMDTY67=duty; //设置占空比寄存器
PWMEnable(6); //使能通道6;
PWMEnable(7); //使能通道7;
break;
default:break;
}
}
定时器应用程序
#include 《hidef.h》 /* common defines and macros */
#include “derivative.h” /* derivative-specific definitions */
// 函数声明
void OutputCompare_Init(void);;
void Service_WD(void);
void SetBusClock_24MHz(void);
// 全局变量
uint Timer7_Cnt=0;
void main(void) {
/* put your own code here */
SetBusClock_24MHz();
OutputCompare_Init();
EnableInterrupts;
for(;;) {
_FEED_COP(); /* feeds the dog */
} /* loop forever */
/* please make sure that you never leave main */
}
void OutputCompare_Init(void)
{
TSCR1_TEN = 0; /* Disable Timer module before adjusting registers. */
TIOS_IOS7 = 1; /* Set Channel 0 as output compare. */
TCTL1_OM7 = 0; /* Set channel 0 to toggle when a Timer match occurs. */
TCTL1_OL7 = 1; /* Set channel 0 to toggle when a Timer match occurs. */
TC7 = 0x4926; /* Set a value for channel 0 timer compare. */
TIE_C7I = 1; /* Enable channel 0 interrupt, handled by function TIM0ISR. */
TSCR1_TSWAI = 1; /* Disables the timer module while in wait mode. */
TSCR1_TSFRZ = 1; /* Disables the timer counter while in freeze mode. */
TSCR2_PR = 0x7; /* Set prescaler to divide by 128 */
TSCR2_TCRE = 1;
TSCR1_TEN = 1; /* Timer Enable. */
//中断周期:0x4926*128/24MHz = 100ms
}
#pragma CODE_SEG __NEAR_SEG NON_BANKED
void interrupt VectorNumber_Vtimch7 TIM7_ISR(void)
{
Timer7_Cnt++;
TFLG1 = TFLG1_C7F_MASK; /* Clear channel 0 flag. */
}
#pragma CODE_SEG DEFAULT
// 看门狗
void Service_WD(void)
{
CPMUARMCOP = 0x55;
CPMUARMCOP = 0xAA;
}
void SetBusClock_24MHz(void)
{
CPMUOSC_OSCE = 1; /* enable ext osc */
/*
Initialise the system clock from a 16 MHz Crystal,
24 MHz Bus CLK (48 MHz VCO, 48 MHz PLL)
*/
CPMUSYNR = 0x00 | 0x05; /* VCOFRQ[7:6], SYNDIV[5:0] */
CPMUREFDIV = 0x20 | 0x03; /* REFFRQ[7:6], REFDIV[3:0] */
CPMUPOSTDIV = 0x00; /* POSTDIV = 0 FPLL = FVCO */
while(!CPMUFLG_LOCK); /* wait for VCO to stabilize*/
Service_WD();
CPMUCLKS_PLLSEL = 1; /* Switch clk to use PLL */
}
SCI应用程序
#include 《hidef.h》 /* common defines and macros */
#include “derivative.h” /* derivative-specific definitions */
// 函数声明
void SCI0_Init(void);
void SCI0_BR(unsigned long br);
void SCI0_SendByte(char ch);
void Service_WD(void);
void SetBusClock_24MHz(void);
// 全局变量
char SCI_Flag = 0;
char SCI_Rev = 0;
void main(void) {
/* put your own code here */
SetBusClock_24MHz();
SCI0_BR(38400);
SCI0_Init();
EnableInterrupts;
SCI0_SendByte(0x01);
SCI0_SendByte(0x02);
SCI0_SendByte(0x03);
for(;;) {
_FEED_COP(); /* feeds the dog */
if(SCI_Flag==1) {
SCI_Flag = 0;
SCI0_SendByte(SCI_Rev);
}
} /* loop forever */
/* please make sure that you never leave main */
}
void Service_WD(void)
{
CPMUARMCOP = 0x55;
CPMUARMCOP = 0xAA;
}
void SetBusClock_24MHz(void)
{
CPMUOSC_OSCE = 1; /* enable ext osc */
/*
Initialise the system clock from a 16 MHz Crystal,
24 MHz Bus CLK (48 MHz VCO, 48 MHz PLL)
*/
CPMUSYNR = 0x00 | 0x05; /* VCOFRQ[7:6], SYNDIV[5:0] */
CPMUREFDIV = 0x20 | 0x03; /* REFFRQ[7:6], REFDIV[3:0] */
CPMUPOSTDIV = 0x00; /* POSTDIV = 0 FPLL = FVCO */
while(!CPMUFLG_LOCK); /* wait for VCO to stabilize*/
Service_WD();
CPMUCLKS_PLLSEL = 1; /* Switch clk to use PLL */
}
//串口初始化
void SCI0_Init(void)
{
SCI0CR1 = 0x00; /* 8 Data Bits, 1 Start Bit, 1 Stop Bit, No Parity */
SCI0CR2 = 0x2C; /* 使能接收中断;使能 Tx,Rx */
/* SCIASR1, SCIACR1, SCIACR2, SCISR1, SCISR2, SCIDRH & SCIDRL left at default values */
}
//串口波特率设置
void SCI0_BR(unsigned long br)
{
uint brPrescaler;
brPrescaler = (uint)(24000000 / (16 * br));
/* Set the Baud Rate */
SCI0BDH = (uchar)((brPrescaler》》8));
SCI0BDL = (uchar)(brPrescaler);
}
//串口发送字节
void SCI0_SendByte(char ch)
{
/* check SCI transmit data register is empty */
while(SCI0SR1_TDRE == 0);
SCI0DRL = ch;
}
//串口中断
#pragma CODE_SEG __NEAR_SEG NON_BANKED
void interrupt VectorNumber_Vsci0 SCI0_ISR(void)
{
SCI0CR2_RIE=0;
while(SCI0SR1_RDRF == 0);
SCI_Rev = SCI0DRL;
SCI_Flag = 1;
SCI0CR2_RIE = 1;
}
#pragma CODE_SEG DEFAULT
ADC应用程序
#include 《hidef.h》 /* common defines and macros */
#include “derivative.h” /* derivative-specific definitions */
// 函数声明
void ADC_Init(void);
uint ADC_GetValue(byte ch);
void Service_WD(void);
void SetBusClock_24MHz(void);
void Delay(void);
// 全局变量
uint AD_Result;
uint AD_Result2;
void main(void) {
/* put your own code here */
SetBusClock_24MHz();
ADC_Init();
EnableInterrupts;
for(;;) {
_FEED_COP(); /* feeds the dog */
AD_Result = ADC_GetValue(7);
AD_Result2 = ADC_GetValue(0);
} /* loop forever */
/* please make sure that you never leave main */
}
// AD初始化
void ADC_Init(void)
{
ATDCTL1 = 0x3F; /* 10-Bit resolution ,discharge before sampling. */
ATDCTL3 = 0x88; /* Right Justified Data, Single conversion sequence */
ATDCTL4 = 0xE1; /* 6 MHz, Notice: 12MHz Max ATD Clock, Fatdlk = FBUS/(2*(PRS+1)) */
/* 26 ATD Clock cycles sample time */
}
// ADC通道采集
uint ADC_GetValue(byte ch)
{
ATDCTL5 = 0x0F & ch; /* Start Continuous Conversions on ch */
while (!ATDSTAT0_SCF); /* wait for conversion sequence to complete */
return ATDDR0;
}
// 看门狗
void Service_WD(void)
{
CPMUARMCOP = 0x55;
CPMUARMCOP = 0xAA;
}
void SetBusClock_24MHz(void)
{
CPMUOSC_OSCE = 1; /* enable ext osc */
/*
Initialise the system clock from a 16 MHz Crystal,
24 MHz Bus CLK (48 MHz VCO, 48 MHz PLL)
*/
CPMUSYNR = 0x00 | 0x05; /* VCOFRQ[7:6], SYNDIV[5:0] */
CPMUREFDIV = 0x20 | 0x03; /* REFFRQ[7:6], REFDIV[3:0] */
CPMUPOSTDIV = 0x00; /* POSTDIV = 0 FPLL = FVCO */
while(!CPMUFLG_LOCK); /* wait for VCO to stabilize*/
Service_WD();
CPMUCLKS_PLLSEL = 1; /* Switch clk to use PLL */
}
void Delay(void)
{
uint dummy_ctr;
for(dummy_ctr=0; dummy_ctr《0x007f;dummy_ctr++)
{
;
}
}
飞思卡尔XS128和G128两种单片机的主要区别
一 端口
XS128有A, B, E, K, T, S, M, P, H, J, 和 AD口。 G128有A, B, C, D, E, T, S, M, P, J 和 AD口。 对于引脚数较少的封装会缺少某些端口。 当端口用作普通IO口时的相关寄存器命名规律相同,一般可以直接移植。 一些引脚的外部中断功能的寄存器配置也一样。但中断号不同。 一些引脚的个别功能可能会不同,但一般很少用。 当端口用作AD,PWM,SCI,SPI,CAN等功能时XS128和G128的引脚用法类似。
二 中断
在CodeWarrior里使用中断向量号,可用如下方法查看到。 点File,选Find and Open File,输入mc9s12g128.h,点OK,打开一个.h文件。往下翻就是中断向量表了。这个XS128和G128可能是不同的,替换一下自己程序中的向量号就行了。不要乱改这个.h文件。
三 时钟配置
这个很重要,虽然两款单片机的相关寄存器名称不同。但计算公式是相同的,见程序注释: 设fosc=16MHz,例如:
2XS128官方规定的上限频率是40M,G128的是25M。把XS128超频到64M问题不大,但把G128超频到64M使用可能会影响系统稳定甚至影响使用寿命。 当G128超到64M时,可能产生开机后无法成功运行PLL而导致单片机不能工作的情况。强烈建议不要超频过多。 文章的最后附上与时钟配置相关的主要寄存器的中文翻译。
四 模数转换器
只需注意XS128有8位,10位,12位三种模式,G128只有8位和10位两种模式。这个在ATDCTL1寄存器中设置。 其它设置基本相同,直接移植问题不大。寄存器名可能有细微差别,例如XS128中是ATD0DR0,而G128是ATDDR0。
五 定时
XS128中的PIT,G128没有。G128中有API,用Timer也行。 六 PWM,SCI,SPI,CAN等 基本相同,直接移植问题不大。
七 Timer模块 基本相同。
全部0条评论
快来发表一下你的评论吧 !