主流16位单片机学习详解:飞思卡尔MC9S12G系列

控制/MCU

1877人已加入

描述

  电子发烧友网:随着驾驶员对车内舒适度和便利性的要求在提高,汽车车身电子产品在保持具有竞争力价格的同时,还需要继续提供性能更高的半导体。飞思卡尔半导体目前开始扩大现已普及的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模块 基本相同。

 

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
评论(0)
发评论
荒野 2015-08-17
0 回复 举报
有代码 很好 收起回复
cxc119110590 2012-11-26
0 回复 举报
很好 收起回复
全部评论

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分