MC9S12XS128 串口操作例程
- 格式:doc
- 大小:37.50 KB
- 文档页数:8
飞思卡尔16位单片机9S12XS128使用收藏最近做一个关于飞思卡尔16位单片机9S12XS128MAA的项目,以前未做过单片机,故做此项目颇有些感触。
现记录下这个艰辛历程。
以前一直是做软件方面的工作,很少接触硬件,感觉搞硬件的人很高深,现在接触了点硬件发现,与其说使用java,C#等语言写程序是搭积木,不如说搞硬件芯片搭接的更像是在搭积木(因为芯片是实实在在拿在手里的东西,而代码不是滴。
还有搞芯片内部电路的不在此列,这个我暂时还不熟悉)。
目前我们在做的这个模块,就是使用现有的很多芯片,然后根据其引脚定义,搭接出我们需要的功能PCB板,然后为其写程序。
废话不多说,进入正题。
单片机简介:9S12XS128MAA单片机是16位的单片机80个引脚,CPU是CPU12X,内部RAM 8KB,EEPROM:2KB,FLASH:128KB,外部晶振16M,通过内部PLL可得40M总线时钟。
9S12XS128MAA单片机拥有:CAN:1个,SCI:2个,SPI:1个,TIM:8个,PIT:4个,A/D:8个,PWM:8个下面介绍下我们项目用到的几个模块给出初始化代码1、时钟模块初始化单片机利用外部16M晶振,通过锁相环电路产生40M的总线时钟(9S12XS128系列标准为40M),初始化代码如下:view plaincopy to clipboardprint?/******************系统时钟初始化****************/void Init_System_Clock(){asm { // 这里采用汇编代码来产生40M的总线LDAB #3STAB REFDVLDAB #4STAB SYNRBRCLR CRGFLG,#$08,*//本句话含义为等待频率稳定然后执行下一条汇编语句,选择此频率作为总线频率BSET CLKSEL,#$80}}/******************系统时钟初始化****************/void Init_System_Clock(){asm { // 这里采用汇编代码来产生40M的总线LDAB #3STAB REFDVLDAB #4STAB SYNRBRCLR CRGFLG,#$08,*//本句话含义为等待频率稳定然后执行下一条汇编语句,选择此频率作为总线频率BSET CLKSEL,#$80}}上面的代码是汇编写的,这个因为汇编代码量比较少,所以用它写了,具体含义注释已经给出,主函数中调用此函数即可完成时钟初始化,总线时钟为40M.2、SCI模块初始化单片机电路做好了当然少不了和PC之间的通信,通信通过单片机串口SCI链接到PC 端的COM口上去。
【MC9S12XS128MAA】使用说明书
预览说明:预览图片所展示的格式为文档的源格式展示,下载源文件没有水印,内容可编辑和复制
MC9XS128MAA 使用说明书
该系统板供电电压为:5±0.02 V ,建议使用TPS7350为其供电,理由如下:TPS7350 是微功耗低压差线性电源芯片,具有完善的保护电路,包括过流、过压、电压反接保护。
使用这个芯片只需要极少的外围元件就能构成高效稳压电路。
与LM2940及AS1117稳压器件相比,TPS7350具有更低的工作压降和更小的静态工作电流,可以使电池获得相对更长的使用时间。
由于热损失小,因此无需专门考虑散热问题。
而且其纹波很小,又为线性稳压芯片,可以为单片机及片外AD 模块提供很稳定的工作电压!
1.到货后检测:
当你的系统板到货后,请你马上测试,如系统板的有个指示灯是一闪一闪的(我们发货检测的时候讲测试程序烧录在里面),证明系统板是没有问题的。
否则就是损坏的,请你马上联系我们的客服。
系统板与下载器BDM的连接图:
该系统板的编程需要专门的飞思卡尔软件:
2.
3.
需要使用USB专用接线,使用前需要安装USB转串口CH340T 驱动
5.烧录时出现问题
如果下载程序步骤不是以上步骤,并且不能进行烧录,则可能出现以下问题:
1、电脑未安装BDM 驱动或者安装未成功;
2、下载线跟芯片下载口的方向不对;
3、连接线出现问题,拔出各接口,重新连接;
4、芯片被锁,请按照解锁文档步骤进行解锁
5、BDM 跳线帽错误。
串行通信分为同步通信和异步通信。
串行通信接口都具有发送引脚TXD和接收引脚RXD,它们是TTL平电。
如果要利用这两个引脚与外界实行异步通信,必须将TTL电平转化为RS-232电平。
SCI是一种全双工异步串行通信接口,主要用于MCU与其他计算机或设备之间的通信,几个独立的MCU也能通过SCI实现串行通信,形成网络。
从编程角度看,先设定好波特率,通信格式,是否校验,是否允许中断等。
接着发送数据时,先检查相应的标志位是否允许发送数据,如果可以,则把数据放入SCI数据寄存器即可,剩下的工作芯片自动完成:将数据从SCI数据寄存器送到发送移位寄存器,硬件驱动将发送移位寄存器里的数据按规定发送到发送引脚TXD,供对方接收。
接收时,数据逐位从接收引脚RXD进入到接收移位寄存器,当收到一个完整字节时,芯片会自动将数据送到SCI数据寄存器,并置相应的标志位,我们就可以根据标志位的情况来读取数据了。
SCIBDH:TNP[1:0]:发送窄脉冲位。
此位的设定与SCI传送的脉冲对应关系如下表:SCIBDL:SBR[12:0]:波特率设定位当IREN=0时,SCI波特率=SCI总线时钟/(16*SBR[12:0])当IREN=1时,SCI波特率=SCI总线时钟/(32*SBR[12:1])SCICR1:控制寄存器1(当AMAP=0时有效)LOOPS:循环模式选择位。
LOOPS=0时,为正常模式。
LOOPS=1时,为自发自收模式,在此模式下,RXD引脚与SCI内部断开,内部发送数据直接作为接收的输入,用于测试。
接收器的输入由RSRC位决定。
SCISWAI:当SCISWAI=0时,SCI可以在等待模式下工作。
当SCISWAI=1时,SCI不可以在等待模式下工作。
RSRC:当LOOPS=1时,RSRC位决定接收移位寄存器接收数据的来源。
RSRC=1,RXD引脚与SCI模块断开,SCI用TXD引脚来发送及接收。
RSRC=0时,发送器的输出作为接收器的输入。
/***************串口发送初始化****************//***************************************************/void uart_init(void){SCI0ACR1=0x00;SCI0CR2=0x0c; //允许发送SCI0BDH=0x00;SCI0BDL=64000000/(115200*16); //xxM}/*********************单个字符发送函数************************ 功能:发送一个字符输入参数:ch输出参数:无*************************************************************/void SCI_Putchar(char ch){while(!(SCI0SR1&0X80)); //检查发送寄存器空标志TDREwhile(!(SCI0SR1&0X40)); //检查发送完成标志TC//=0正在发送=1没有发送SCI0DRL=ch;}/*********************字符串发送函数************************ 功能:发送字符串输入参数:*str输出参数:无*************************************************************/void SCI_Putstr(char *str) //可直接发送中文,比如uart_putstr("个") {for(;*str!=0;str++){SCI_Putchar(*str);}}/*********************单个字符接收函数************************ 功能:接收一个字符输入参数:无输出参数:SCI0DRL寄存器中的字符*************************************************************/byte SCI_getchar(void){while(!SCI0SR1_RDRF); //RDRF 接收数据寄存器满标志//当接收移位寄存器中的数据发动到SCI数据寄存器中时,RDRF置位。
飞思卡尔MC9S12XS128各模块初始化程序--超详细注释//**************************************************************************// 武狂狼2014.5.1 整理// 新手入门的助手////***************************************************************************注释不详细/*********************************************************/函数名称:void ATD0_init(void)函数功能:ATD初始化入口参数:出口参数:/***********************************************************/void ATD0_init(void){ATD0DIEN=0x00; //使用模拟输入功能|=1;数字输入功能// ATD0CTL0=0x07; //Bit[3:0]WRAP[3:0] 反转通道选择位ATD0CTL1=0x40; // 12位精度,采样前不放电 Bit[7]ETRIGSEL(外部触发源选择位。
=0选择A/D通道AN[15:0] |=1选择 ERTIG3~0)和Bit[3:0]ETRIGCH[3:0]选择外部触发通道// Bit[6:5]SRES[1:0]A/D分辨率选择位。
Bit[4]SMP_DIS =0采样前不放电|=1采样前内部电容放电,这会增加2个A/D时钟周期的采样时间,有助于采样前进行开路检测ATD0CTL2=0x40; // 快速清零,禁止中断,禁止外部触发ATD0CTL3=0x90; // 右对齐,转换序列长度为2,非FIFOATD0CTL4=0x03; // 采样时间4个周期,PRS=31,F(ATDCLK)=F(BUS)/(2(PRS+1))// ATD0CTL5=0x30; //启动AD转换序列//:对每项数据采集时,用到哪个通道采样可在相应子函数内设置某一通道(见Sample_AD.c)while(!ATD0STAT2L_CCF0);/*********************************************************/函数名称:void PIT_init(void)函数功能:初始化PIT 设置精确定时时间(1s)入口参数:无出口参数:无说明:无/***********************************************************/void PIT_init(void){PITCFLMT=0x00; //禁止PIT模块Bit[7] PITE:PIT模块使能位,0禁用|1使能// Bit[6] PITSWAI:等待模式下PIT停止位,0等待模式下,PIT模块正常运行| 1等待模式下,PIT模块停止产生时钟信号,冻结PIT模块// Bit[5] PITFRZ: 冻结模式下PIT计数器冻结位。
MC9S12XS128例程SCI程序串行通信时MCU与外部设备之间进行通信的一种简单而有效的硬件方法。
无论用查询方式还是中断方式进行串行通信编程,在程序初始化时均必须对SCI进行初始化。
初始化主要包括波特率设置、通信格式的设置、发送接收数据方式的设置等。
对SCI进行初始化,需要设置如下几部分:(1)定义波特率一般选内部总线时钟为串行通信的时钟源。
通过设置SCI波特率寄存器SCI0BD的波特率选择位SBR[12:0],来选择合适的分频系数。
(2)写控制字到SCI控制寄存器1(SCI0CR1)设置是否允许SCI、数据长度、输出格式、选择唤醒方法、是否校验等。
(3)写控制字到SCI控制寄存器2(SCI0CR2)设置是否允许发送与接收、是中断接收还是查询接收等。
串行通信程序如下:/** write in “Init.h” **/#include /* 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的中断向量号为20 byte 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,然后通过控制寄存器发出转换命令,即可实现转换。
实验一MC9S12XS128入门实验一.实验目的1.熟悉CodeWarrior嵌入式开发系统软硬件环境,掌握其使用方法及调试方式。
2.掌握S12 GPIO接口的使用方法及编程方法。
3.熟悉S12单片机的C语言程序编程框架。
4.理解样例中的第一个C语言程序代码。
二.实验设备及其连接1.PC机一台2.S12嵌入式开发实验箱一套3.接线图图1-1 I/O口实验接线图GNDKEY1-8)三.实验内容1.使用CodeWarrior嵌入式开发系统的软硬件环境,掌握其使用方法及调试方式。
2.调试运行提供的样例程序light,观看实验结果。
(软件使用参见第四部分)3.运行样例程序,观察小灯的闪烁和对应的程序实现;调整延时的长短,继续观察小灯的闪烁。
4.尝试新建自己的工程,自编程序,实现用4个开关控制4个小灯的亮灭. 4个开关分别接在端口A的PTA4~PTA7口,小灯则接在PTA0~PTA3口, 参见第二部分连接图. 编程实现用这4个开关控制4个小灯,开关拨在“H”时,对应小灯亮,否则为暗。
(可参考教材P119-120页实例,注意教材中使用PORTB,实验箱使用PORTA)提示:新建工程时芯片选择HCS12X family-〉mc9s12xs128,connection 选择TBDML,然后下一步输入工程路径和名称,再3次下一步,选择默认选项,然后下一步、完成。
在main.c 文件中加入你的代码,主要通过设置数据方向寄存器DDRA和数据寄存器PORTA来实现开关控制小灯的功能。
代码举例:(具体编程时要作修改)DDRA= 0xff; //将端口A的8个管脚都设为输出。
PORTA&= 0xf0;//将端口A的低4脚输出0,低4位连接的灯被点亮Temp=PORTA & 0xf0;//读入端口A的高4脚的状态Temp1 =temp>>4; //temp右移4位四.CodeWarrior嵌入式开发环境的基本使用方法1.运行CodeWarrior IDE嵌入式开发平台,点击菜单命令“File\Open”打开light文件夹中的project.mcp工程文件,按F7或者Project\Make菜单编译,若有错,修改再编译直至通过。
第一章端口整合模块端口A,B和K为通用I/O接口端口E整合了IRQ,XIRQ中断输入端口T整合了1个定时模块端口S整合了2个SCI模块和1个SPI模块端口M整合了1个MSCAN端口P整合了PWM模块,同时可用作外部中断源输入端口H和J为通用I/O接口,同时可用作外部中断源输入端口AD整合了1个16位通道ATD模块大部分I/O引脚可由相应的寄存器位来配置选择数据方向、驱动能力,使能上拉或下拉式装置。
当用作通用IO口时,所有的端口都有数据寄存器和数据方向寄存器。
对于端口T,S,M,P,H,和J有基于每个针脚的上拉和下拉控制寄存器。
对于端口AD有基于每个针脚的上拉寄存器。
对于端口A、B、E和K,有一个基于端口的上拉控制寄存器。
对于端口T,S,M,P,H,J,和AD,有基于每个针脚的降额输出驱动控制寄存器。
对于端口A,B,E,和K,有一个基于端口的降额输出驱动控制寄存器。
对于端口S、M,有漏极开路(线或)控制寄存器。
对于端口P、H和J,有基于每个针脚的中断标志寄存器。
纯通用IO端口共计有41个,分别是:PA[7:0]PB[7:0]PE[6:5]PE[3:2]PK[7,5:0]PM[7:6]PH[7:0](带中断输入)PJ[7:6](带中断输入)PJ[1:0](带中断输入)第二章脉冲宽度调制模块XS128具有8位8通道的PWM,相邻的两个通道可以级联组成16位的通道。
PWME::PWMEPWM通道使能寄存器。
PWMEx=1将立即使能该通道PWM波形输出。
若两个通道级联组成一个16位通道,则低位通道(通道数大的)的使能寄存器成为该级联通道的使能寄存器,高位通道(通道数小的)的使能寄存器和高位的波形输出是无效的。
PWMPOLPWMPOL::PWM极性寄存器。
PPOLx=1,则该通道的周期初始输出为高电平,达到占空比后变为低电平;相反,若PPOLx=0,则初始输出为低电平,达到占空比后变为高电平。
PWMCLK::PWMCLKPWM时钟源选择寄存器。
MC9S12XS128开収板实验挃导手册目录第1章MC9S12XS128开収板概述 (4)第2章MC9S12XS128开収板结极 (10)第3章CodeWarrior快速入门 (17)3.1安装CodeWarrior软件 (17)3.2安装BDM驱动 (17)3.3创建新工程 (17)3.4调试新建工程 (21)第4章基础实验 (25)实验一复位及看门狗 (25)实验二蜂鸣器实验 (27)实验三LED灯实验 (28)实验四按键实验 (29)实验五ATD实验 (33)实验六锁相环实验 (37)实验七SCI串口实验 (38)实验八PWM实验 (41)实验九TIM实验 (42)实验十实时中断实验 (44)实验十一PIT实验 (45)实验十二数码管实验 (46)第5章高级实验 (47)实验一数字电压表 (47)实验二数字秒表及定时器 (48)实验三蜂鸣器播放音乐 (50)实验四汉显液晶实验 (51)实验五ZX0802A小液晶实验 (52)实验六遥控模块实验 (54)实验七温度传感器实验 (56)实验八RS-485总线实验 (58)实验九LIN总线实验 (59)实验十CAN总线实验 (63)实验十一SAE-J1939实验 (66)实验十二SD卡实验 (67)实验十三综合演示实验 (69)第6章补充实验 (70)实验一DFLASH实验 (70)版权所有盗用必究第1章MC9S12XS128开収板概述MC9S12XS128 (以下简称XS128)开収板是由“飞翔科技”基于XS128单片机的功能而开収的一款开収板。
该开収板硬件资源丰富,布局清晰明了,利用该开収板的硬件资源可熟悉和掌握XS128单片机的功能,充分体现出汽车电子的特色。
本部分将对XS128开収板的功能迚行简单介绍,以方便用户快速了解该开収板的功能。
下图为XS128开収板实物图。
与开収板配合使用的还有以下几个配件:跳线帽单股跳线连接线双股跳线连接线12V电源适配器串口延长线可以选配的配件主要有:BDM下载器12864汉显液晶模块ZX0802A小液晶无线遥控模块该开収板可分20个功能模块,下面简单介绍每个功能模块:●电源电路:电源模块使用LM2940芯片,将12V的电源转换成5V的电源,并使用LM1117芯片将5V的电源转换为3.3V,以便给SD卡供电。
//------------------------------------------------------------------------------------------------------------------// //功能说明:MC9S12XS128--A TD例程//使用说明:由通道A TD0进行多通道A/D转换,转换值在B口显示//----------------------------------------------------------------------------------------------------------------// #include<hidef.h> /*commondefinesandmacros*/#include"derivative.h" /*derivative-specificdefinitions*///头文件//头文件Word AD_wV alue;//AD转换结果WORD的类型定义如下://typedef unsigned short WORD//它就是无符号短整型类型(16bit的无符号短整数)// 变量//--------------初始化函数----------------////-----时钟初始化程序--------//void PLL_Init(void) //PLLCLK=2*OSCCLK*(SYNR+1)/(REFDV+1){ //锁相环时钟=2*16*(2+1)/(1+1)=48MHzREFDV=1; //总线时钟=48/2=24MHzSYNR=2;while(!(CRGFLG&0x08));CLKSEL=0x80;}//-----A TD初始化程序--------//void AD_Init(void){A TD0CTL1=0x00; //选择AD通道为外部触发,8位精度,采样前不放电A TD0CTL2=0x40; //标志位自动清零,禁止外部触发, 禁止中断A TD0CTL3=0xa0; //右对齐无符号,每次转换4个序列, NoFIFO,Freeze模式下继续转//转换序列在多通道选择下,是表示用几个通道来转换;在单通道下,是表示这一个通道中//转换几次。
1.对IO口输入输出操作程序举例:A口接流水灯并实现闪烁void main(void) {while(1){DDRA=0xff;delay(500);PORTA=0xff;delay(500);PORTA=0;}另外,B、E口的IO功能操作也是一样的,因为位数一样寄存器一样,其他口的寄存器就不太一样了!J,P,M,T,S这五个口除具有数据寄存器外,他们都另外多出另一个端口输入寄存器(该寄存器功能我未知)!2.SPI总线接口SPI是一种高速高效的同步串行接口,这种接口主要用于MCU与外部的接口芯片交换数据,只要有SPI口的芯片都可以与单片机相连形成主从机系统进行数据的传递,比如SPI用于移位寄存器74HC164,这是个串入并出的芯片这样可以实现扩展IO口。
还有AD转换芯片AD7793,可以实现数模转换,还有飞思卡尔公司的电源管理芯片MC33389。
因设备有限此功能待以后调试!3.SCI总线接口MC9S12DG128单片机有两个SCI模块,可以选用其中任何一个。
他的使用有8个相应寄存器共设置,其中有波特率设置寄存器SCIBDH,SCIBDL,还有控制寄存器SCICR1,SCICR2,状态寄存器SCISR1,SCISR2,数据寄存器SCIDRH,SCIDRL;简单讲SCI的使用就是寄存器初始化,数据传送方式设置,下面举个初始化使用的简单例子:SCICR2=0x08;//发送使能设置SCIBDH=0x00;//波特率设置为9600SCIBDL=0x9c;就是这样这个是简单实用时的设置,发送函数如下:While(!(SCISR1&0x40))//检测是否发送完毕,一旦发送完毕就进入到死循环里边{}SCIDRL=C;//C代表需要传送的数据4.有关定时器TCNTTCNT是芯片内部的16位主定时器,他不停地对内部时钟信号进行计数,从0x0000直到0xffff,计满后溢出又返回到0x0000,程序随时可以读取,但在普通模式下禁止写入。
MC9S12XS128串口操作例程MC9S12XS128 串口操作例程Code Warrior 4.7Target : MC9S12XS128Crystal: 16.000Mhzbusclock: 8.000MHzpllclock:16.000MHz本程序主要包括以下功能:1.设置锁相环和总线频率;2.IO口使用;3.共四路ATD使用及显示方法。
LED计数,根据灯亮可以读取系统循环了多少次************************************************************** ***************************/#include /* common defines and macros */#include /* derivative information */#include#include#include#pragma LINK_INFO DERIVATIVE "mc9s12xs128"#pragma CODE_SEG DEFAULT#define CR_as_CRLF TRUE // if true , you can use "\n" to act as CR/LF,// if false, you have to use "\n\r",but can get a higher speed static int do_padding;static int left_flag;static int len;static int num1;static int num2;static char pad_character;unsigned char uart_getkey(void){while(!(SCI0SR1&0x80)) ; //keep waiting when not emptyreturn SCI0DRL;}/*void uart_init(void) {SCI0CR2=0x0c;SCI0BDH=0x00;//16MHz,19200bps,SCI0BDL=0x1aSCI0BDL=0x34;//16MHz,9600bps,SCI0BDL=0x34}*/void uart_putchar(unsigned char ch){if (ch == '\n'){while(!(SCI0SR1&0x80)) ;SCI0DRL= 0x0d; //output'CR'return;}while(!(SCI0SR1&0x80)) ; //keep waiting when not empty SCI0DRL=ch;}void putstr(char ch[]){unsigned char ptr=0;while(ch[ptr]){uart_putchar((unsigned char)ch[ptr++]);}}static void padding( const int l_flag){int i;if (do_padding && l_flag && (len < num1))for (i=len; i<="" p="">uart_putchar( pad_character);}static void outs( char* lp){/* pad on left if needed */len = strlen( lp);padding( !left_flag);/* Move string to the buffer */while (*lp && num2--) uart_putchar( *lp++);/* Pad on right if needed */len = strlen( lp);padding( left_flag);}static void reoutnum(unsigned long num, unsigned int negative, const long base ){char* cp;char outbuf[32];const char digits[] = "0123456789ABCDEF";/* Build number (backwards) in outbuf */cp = outbuf;do {*cp++ = digits[(int)(num % base)];} while ((num /= base) > 0);if (negative) *cp++ = '-';*cp-- = 0;/* Move the converted number to the buffer and *//* add in the padding where needed. */len = strlen(outbuf);padding( !left_flag);while (cp >= outbuf)uart_putchar( *cp--);padding( left_flag);}static void outnum(long num, const long base ,unsigned char sign)//1, signed 0 unsigned{unsigned int negative;if ( (num < 0L) && sign ){negative=1;num = -num;}else negative=0;reoutnum(num,negative,base);}static int getnum( char** linep){int n;char* cp;n = 0;cp = *linep;while (isdigit(*cp))n = n*10 + ((*cp++) - '0');*linep = cp;return(n);}void printp( char* ctrl, ...){int long_flag;int dot_flag;char ch;va_list argp;va_start( argp, ctrl);for ( ; *ctrl; ctrl++) {/* move format string chars to buffer until a format control is found. */ if (*ctrl != '%') {uart_putchar(*ctrl);#if CR_as_CRLF==TRUEif(*ctrl=='\n') uart_putchar('\r');#endifcontinue;}/* initialize all the flags for this format. */dot_flag = long_flag = left_flag = do_padding = 0;pad_character = ' ';num2=32767;try_next:ch = *(++ctrl);if (isdigit(ch)){if (dot_flag)num2 = getnum(&ctrl);else {if (ch == '0')pad_character = '0';num1 = getnum(&ctrl);do_padding = 1;}ctrl--;goto try_next;}switch (tolower(ch)) {case '%':uart_putchar( '%');continue;case '-':left_flag = 1;break;case '.':dot_flag = 1;break;case 'l':long_flag = 1;break;case 'd':if (long_flag ==1 ){if(ch == 'D') {outnum( va_arg(argp, unsigned long), 10L , 0);continue;}else /* ch == 'd' */ {outnum( va_arg(argp, long), 10L,1);continue;}}else{if(ch == 'D') {outnum( va_arg(argp, unsigned int),10L,0);continue;}else /* ch == 'd' */{outnum( va_arg(argp, int), 10L,1); continue;}}case 'x': // X 无符号,x 有符号if (long_flag ==1 ){if(ch == 'X'){outnum( va_arg(argp, unsigned long), 16L,0); continue;}else /* ch == 'x' */{outnum( va_arg(argp, long), 16L,1); continue;}}else{if(ch == 'X'){outnum( va_arg(argp, unsigned int), 16L,0); continue;}else /* ch == 'x' */{outnum( va_arg(argp, int), 16L,1);continue;}} //如果按照16进制打印,将全部按照无符号数进行continue;case 's':outs( va_arg( argp, char*));continue;case 'c':uart_putchar( va_arg( argp, int));continue;default:continue;}goto try_next;}va_end( argp);}#pragma CODE_SEG __NEAR_SEG NON_BANKED void interrupt 20 SCI0_ISR(void){SCI0CR2_RIE=0;//此处为串口中断需要处理的事情uart_putchar(uart_getkey());PORTA_PA0=~PORTA_PA0;SCI0CR2_RIE = 1;}#pragma CODE_SEG DEFAULT//-----------------------------------------------------void setbusclock(void){CLKSEL=0X00; //disengage PLL to systemPLLCTL_PLLON=1; //turn on PLLSYNR=1;REFDV=1; //pllclock=2*osc*(1+SYNR)/(1+REFDV)=32MHz;_asm(nop); //BUS CLOCK=16M_asm(nop);while(!(CRGFLG_LOCK==1)); //when pll is steady ,then use it;CLKSEL_PLLSEL =1; //engage PLL to system;}//-----------------------------------------------------static void SCI_Init(void){SCI0CR1 =0x00;SCI0CR2 =0x2c; //enable Receive Full Interrupt,RX enable,Tx enable SCI0BD =0x68; //SCI0BDL=busclk/(16*SCI0BDL) //busclk 8MHz, 9600bps,SCI0BD=0x34//busclk 16MHz, 9600bps,SCI0BD=0x68//busclk 24MHz, 9600bps,SCI0BD=0x9C} //busclk 32MHz, 9600bps,SCI0BD=0xD0//busclk 40MHz, 9600bps,SCI0BD=0x106//-----------------------------------------------------void Dly_ms(int ms){int ii,jj;if (ms<1) ms=1;for(ii=0;ii<ms;ii++)< p="">for(jj=0;jj<2670;jj++); //busclk:16MHz--1ms}void main(void){unsigned char LedCnt=0;setbusclock();SCI_Init();DDRA=0xFF;PUCR_PUPBE=1;EnableInterrupts;for(;;){LedCnt=(LedCnt>0XFE?0:++LedCnt);Dly_ms(1000); //修改延时以修改数据发送频率//低电平灯亮用这句,注释掉下面那句PORTA_PA0=~PORTA_PA0;//高电平灯亮用这句,注释掉上面那句//PORTB=LedCnt;putstr("\nhttp:%/%//doc/4115489903.html,");printp("\n Minute elapsed: %03ds",LedCnt); }}</ms;ii++)<>。
MC9S12XS128 串口操作例程Code Warrior 4.7Target : MC9S12XS128Crystal: 16.000Mhzbusclock: 8.000MHzpllclock:16.000MHz本程序主要包括以下功能:1.设置锁相环和总线频率;2.IO口使用;3.共四路ATD使用及显示方法。
LED计数,根据灯亮可以读取系统循环了多少次************************************************************** ***************************/#include <hidef.h> /* common defines and macros */#include <MC9S12XS128.h> /* derivative information */#include <ctype.h>#include <string.h>#include <stdarg.h>#pragma LINK_INFO DERIVATIVE "mc9s12xs128"#pragma CODE_SEG DEFAULT#define CR_as_CRLF TRUE // if true , you can use "\n" to act as CR/LF,// if false, you have to use "\n\r",but can get a higher speedstatic int do_padding;static int left_flag;static int len;static int num1;static int num2;static char pad_character;unsigned char uart_getkey(void){while(!(SCI0SR1&0x80)) ; //keep waiting when not emptyreturn SCI0DRL;}/*void uart_init(void) {SCI0CR2=0x0c;SCI0BDH=0x00;//16MHz,19200bps,SCI0BDL=0x1aSCI0BDL=0x34;//16MHz,9600bps,SCI0BDL=0x34}*/void uart_putchar(unsigned char ch){if (ch == '\n'){while(!(SCI0SR1&0x80)) ;SCI0DRL= 0x0d; //output'CR'return;}while(!(SCI0SR1&0x80)) ; //keep waiting when not empty SCI0DRL=ch;}void putstr(char ch[]){unsigned char ptr=0;while(ch[ptr]){uart_putchar((unsigned char)ch[ptr++]);}}static void padding( const int l_flag){int i;if (do_padding && l_flag && (len < num1))for (i=len; i<num1; i++)uart_putchar( pad_character);}static void outs( char* lp){/* pad on left if needed */len = strlen( lp);padding( !left_flag);/* Move string to the buffer */while (*lp && num2--) uart_putchar( *lp++);/* Pad on right if needed */len = strlen( lp);padding( left_flag);}static void reoutnum(unsigned long num, unsigned int negative, const long base ){char* cp;char outbuf[32];const char digits[] = "0123456789ABCDEF";/* Build number (backwards) in outbuf */cp = outbuf;do {*cp++ = digits[(int)(num % base)];} while ((num /= base) > 0);if (negative) *cp++ = '-';*cp-- = 0;/* Move the converted number to the buffer and *//* add in the padding where needed. */len = strlen(outbuf);padding( !left_flag);while (cp >= outbuf)uart_putchar( *cp--);padding( left_flag);}static void outnum(long num, const long base ,unsigned char sign)//1, signed 0 unsigned{unsigned int negative;if ( (num < 0L) && sign ){negative=1;num = -num;}else negative=0;reoutnum(num,negative,base);}static int getnum( char** linep){int n;char* cp;n = 0;cp = *linep;while (isdigit(*cp))n = n*10 + ((*cp++) - '0');*linep = cp;return(n);}void printp( char* ctrl, ...){int long_flag;int dot_flag;char ch;va_list argp;va_start( argp, ctrl);for ( ; *ctrl; ctrl++) {/* move format string chars to buffer until a format control is found. */ if (*ctrl != '%') {uart_putchar(*ctrl);#if CR_as_CRLF==TRUEif(*ctrl=='\n') uart_putchar('\r');#endifcontinue;}/* initialize all the flags for this format. */dot_flag = long_flag = left_flag = do_padding = 0;pad_character = ' ';num2=32767;try_next:ch = *(++ctrl);if (isdigit(ch)){if (dot_flag)num2 = getnum(&ctrl);else {if (ch == '0')pad_character = '0';num1 = getnum(&ctrl);do_padding = 1;}ctrl--;goto try_next;}switch (tolower(ch)) {case '%':uart_putchar( '%');continue;case '-':left_flag = 1;break;case '.':dot_flag = 1;break;case 'l':long_flag = 1;break;case 'd':if (long_flag ==1 ){if(ch == 'D') {outnum( va_arg(argp, unsigned long), 10L , 0);continue;}else /* ch == 'd' */ {outnum( va_arg(argp, long), 10L,1);continue;}}else{if(ch == 'D') {outnum( va_arg(argp, unsignedint),10L,0);continue;}else /* ch == 'd' */{outnum( va_arg(argp, int), 10L,1);continue;}}case 'x': // X 无符号,x 有符号if (long_flag ==1 ){if(ch == 'X'){outnum( va_arg(argp, unsigned long), 16L,0);continue;}else /* ch == 'x' */{outnum( va_arg(argp, long), 16L,1);continue;}}else{if(ch == 'X'){outnum( va_arg(argp, unsigned int), 16L,0);continue;}else /* ch == 'x' */{outnum( va_arg(argp, int), 16L,1);continue;}} //如果按照16进制打印,将全部按照无符号数进行continue;case 's':outs( va_arg( argp, char*));continue;case 'c':uart_putchar( va_arg( argp, int));continue;default:continue;}goto try_next;}va_end( argp);}#pragma CODE_SEG __NEAR_SEG NON_BANKEDvoid interrupt 20 SCI0_ISR(void){SCI0CR2_RIE=0;//此处为串口中断需要处理的事情uart_putchar(uart_getkey());PORTA_PA0=~PORTA_PA0;SCI0CR2_RIE = 1;}#pragma CODE_SEG DEFAULT//-----------------------------------------------------void setbusclock(void){CLKSEL=0X00; //disengage PLL to systemPLLCTL_PLLON=1; //turn on PLLSYNR=1;REFDV=1; //pllclock=2*osc*(1+SYNR)/(1+REFDV)=32MHz;_asm(nop); //BUS CLOCK=16M_asm(nop);while(!(CRGFLG_LOCK==1)); //when pll is steady ,then use it;CLKSEL_PLLSEL =1; //engage PLL to system;}//-----------------------------------------------------static void SCI_Init(void){SCI0CR1 =0x00;SCI0CR2 =0x2c; //enable Receive Full Interrupt,RX enable,Tx enable SCI0BD =0x68; //SCI0BDL=busclk/(16*SCI0BDL)//busclk 8MHz, 9600bps,SCI0BD=0x34//busclk 16MHz, 9600bps,SCI0BD=0x68//busclk 24MHz, 9600bps,SCI0BD=0x9C} //busclk 32MHz, 9600bps,SCI0BD=0xD0//busclk 40MHz, 9600bps,SCI0BD=0x106//-----------------------------------------------------void Dly_ms(int ms){int ii,jj;if (ms<1) ms=1;for(ii=0;ii<ms;ii++)for(jj=0;jj<2670;jj++); //busclk:16MHz--1ms}void main(void){unsigned char LedCnt=0;setbusclock();SCI_Init();DDRA=0xFF;PUCR_PUPBE=1;EnableInterrupts;for(;;){LedCnt=(LedCnt>0XFE?0:++LedCnt);Dly_ms(1000); //修改延时以修改数据发送频率//低电平灯亮用这句,注释掉下面那句PORTA_PA0=~PORTA_PA0;//高电平灯亮用这句,注释掉上面那句//PORTB=LedCnt;putstr("\n http:%/%/");printp("\n Minute elapsed: %03ds",LedCnt); }}。