飞思卡尔MC9S12单片机实验程序
- 格式:doc
- 大小:37.00 KB
- 文档页数:6
飞思卡尔MC9S12XS128单片机各模块使用方法及寄存器配置手把手教你写S12XS128程序--PWM模块介绍该教程以MC9S12XS128单片机为核心进行讲解,全面阐释该16位单片机资源。
本文为第一讲,开始介绍该MCU的PWM模块。
PWM 调制波有8个输出通道,每一个输出通道都可以独立的进行输出。
每一个输出通道都有一个精确的计数器(计算脉冲的个数),一个周期控制寄存器和两个可供选择的时钟源。
每一个P WM 输出通道都能调制出占空比从0—100% 变化的波形。
PWM 的主要特点有:1、它有8个独立的输出通道,并且通过编程可控制其输出波形的周期。
2、每一个输出通道都有一个精确的计数器。
3、每一个通道的P WM 输出使能都可以由编程来控制。
4、PWM 输出波形的翻转控制可以通过编程来实现。
5、周期和脉宽可以被双缓冲。
当通道关闭或PWM 计数器为0时,改变周期和脉宽才起作用。
6、8 字节或16 字节的通道协议。
7、有4个时钟源可供选择(A、SA、B、SB),他们提供了一个宽范围的时钟频率。
8、通过编程可以实现希望的时钟周期。
9、具有遇到紧急情况关闭程序的功能。
10、每一个通道都可以通过编程实现左对齐输出还是居中对齐输出。
1、PWM启动寄存器PWMEPWME 寄存器每一位如图1所示:复位默认值:0000 0000B图1 PWME 寄存器每一个PWM 的输出通道都有一个使能位P WMEx 。
它相当于一个开关,用来启动和关闭相应通道的PWM 波形输出。
当任意的P WMEx 位置1,则相关的P WM 输出通道就立刻可用。
用法:PWME7=1 --- 通道7 可对外输出波形PWME7=0 --- 通道7 不能对外输出波形注意:在通道使能后所输出的第一个波形可能是不规则的。
当输出通道工作在串联模式时(PWMCTL 寄存器中的CONxx置1),那么)使能相应的16位PWM 输出通道是由PWMEx 的高位控制的,例如:设置PWMCTL_CON01 = 1,通道0、1级联,形成一个16位PWM 通道,由通道 1 的使能位控制PWM 的输出。
飞思卡尔程序#include <hidef.h> /* common defines andmacros */#include <mc9s12dg128.h> /* derivativeinformation *///#include "PWM.h"//#include "AD.h"#include "control.h"#pragma LINK_INFO DERIVATIVE "mc9s12dg128b"word AD_wData[9]; //全局变量存放 AD0,AD1,AD2的结果word sum[9]; //初始化时为求平均值,全白中,各个灯的FF次的电压和word avrg0[9]; //全白时各个灯的平均电压word summ[9];//初始化时为求平均值,全黑中,各个灯的FF次的电压和word avrg1[9]; //全黑时各个灯的平均电压word ss[9]; //实际采集来的各个灯的电压word s[9]; // 实际采集来的各个灯的电压word sum2[8];//用于存放两两灯电压之和word k; //用于存放比较出的最大值uint h=1500;//转角大小int flag = 0;//标志中间灯是否第一次在黑道附近int flagg=0;//标志0灯从哪边感应到黑道int flagg1=0;//标志8灯从哪边感应到黑道int flagg0=0;//标志是左边还是右边出道int j=0;dword i;dword m;dword s0;dword s1;dword p11=0;//以下四个变量用于记录黑道处于同一侧的时间dword p12=0;dword p21=0;dword p22=0;word max0[9]=0;//初始化时采集来的黑道的值int g=0;//为过滤算法使用word cha[9];//用来存放黑白电压差int ffgg0=0;//标志是否用中间板采的数据int ffgg1=0;//标志是否用中间板采的数据word sum0=0; //初始化时采集来9个灯的全白电压和//word sum1=0; //实际采集来的左4个灯的电压和//word sum22=0; //实际采集来的右4个灯的电压和int fla=0;//标志是出道还是入道void AD_Init();void PWM_Init();void PWM_Init1();//void PID();void AD_Init(void) //AD初始化{//控制寄存器2:上电,标志位快速清零,开中断ATD0CTL2 =(ATD0CTL2_ADPU_MASK|ATD0CTL2_AFFC_MASK|ATD0CTL2_ASCIE_MASK) ;ATD1CTL2 =(ATD1CTL2_ADPU_MASK|ATD1CTL2_AFFC_MASK|ATD1CTL2_ASCIE_MASK) ;//控制寄存器3:转换序列长度为3ATD0CTL3 =0x78;//(ATD0CTL3_S2C_MASK|ATD0CTL3_S1C_MASK);ATD1CTL3 =0x78;//(ATD1CTL3_S2C_MASK|ATD1CTL3_S1C_MASK);//控制寄存器4:ATD0CTL4 =(ATD0CTL4_SRES8_MASK|ATD0CTL4_PRS1_MASK|ATD0CTL4_PRS0_MASK) ;ATD1CTL4 =(ATD1CTL4_SRES8_MASK|ATD1CTL4_PRS1_MASK|ATD1CTL4_PRS0_MASK) ;//控制寄存器5:ATD0CTL5 =(ATD0CTL5_DJM_MASK|ATD0CTL5_SCAN_MASK|ATD0CTL5_MULT_MASK);ATD1CTL5 =(ATD1CTL5_DJM_MASK|ATD1CTL5_SCAN_MASK|ATD1CTL5_MULT_MASK); ATD0DIEN=0x00; // 禁止数字输入缓冲ATD1DIEN=0x00; // 禁止数字输入缓冲}#pragma CODE_SEG NON_BANKED //中断服务程序#pragma TRAP_PROCvoid interrupt 22 Int_AD0(void){AD_wData[0] = ATD0DR0; //将结果寄存器中的值存放到数组中AD_wData[1] = ATD0DR1; //将结果寄存器中的值存放到数组中AD_wData[2] = ATD0DR2; //将结果寄存器中的值存放到数组中AD_wData[3] = ATD0DR3;AD_wData[4] = ATD0DR4;AD_wData[5] = ATD0DR5;AD_wData[6] = ATD0DR6;AD_wData[7] = ATD0DR7;AD_wData[8] = ATD1DR0;}#pragma CODE_SEG DEFAULTword max(word a,word b,word c,word d,word e,wordf,word r,word w) {word maxx=0;if(a>maxx)maxx=a;if(b>maxx)maxx=b;if(c>maxx)maxx=c;if(d>maxx)maxx=d;if(e>maxx)maxx=e;if(f>maxx)maxx=f;if(r>maxx)maxx=r;if(w>maxx)maxx=w;return maxx;}void delay0(){for(i=0;i<0xFFFF;i++)for(m=0;m<0x05;m++);}void delay1(){for(i=0;i<0xFFFF;i++);// for(i=0;i<0xFFFF;i++);}void main(void){AD_Init(); //AD 初始化DDRB = 0xFF;DDRA_BIT6=0; //A_BIT6口作为第二块板左边传感器的输入口 DDRA_BIT7=0; //A_BIT7口作为第二块板右边传感器的输入口 PORTB = 0xFF;p=0;for(j=0;j<9;j++){AD_wData[j] = 0; //全局变量初始化sum[j]=0;avrg0[j]=0;avrg1[j]=0;summ[j]=0;}for(j=0;j<9;j++) {max0[j]=0;ss[j]=0;}for(j=0;j<8;j++)sum2[j]=0;EnableInterrupts; //开AD中断for(i=0;i<0xFFFF;i++);for(i=0;i<0xFF;i++) //只能是FF,防止下面sum溢出 {for(j=0;j<9;j++)//采集白道路信息{sum[j]=sum[j]+AD_wData[j];}}for(i=0;i<9;i++) {sum0=sum0+sum[i]/0xFF;avrg0[i]=sum[i]/0xFF;}PORTB=sum[0]/0xFF; //显示0通道采集到的值delay0();PORTB=0x00;//显示马上得进行黑道信息采集了delay1();for(j=0;j<9;j++){for(m=0;m<0xFF;m++){summ[j]=summ[j]+AD_wData[j];}avrg1[j]=summ[j]/0xFF;PORTB=avrg1[j]; //显示采来的黑道信息cha[j]=avrg1[j]-avrg0[j];delay0();PORTB=0x00; //显示马上得进行下一次黑道信息采集了 delay1();}PORTB=0x00;//灯全亮,提示车马上就可以跑了delay1();PWM_Init() ;PWM_Init1(1500,1,200);for(i=0;i<0xFFF;i++);// delay1();for(;;){int f=0;u3=100;if(flagk1==1){p21=0;flagk2=0;p11++;if(p11==0xFFF)flagkk1=1;}else if(flagk2==1){p11=0;flagk1=0;p21++;if(p21==0xFFF)flagkk2=1;}for(f=0;f<9;f++){s[f]=AD_wData[f];ss[f]=s[f]-(avrg0[f]-0x50); //当前值减去初始白道值,以便比较}for(f=0;f<8;f++)sum2[f]=ss[f]+ss[f+1]; //两两灯电压之和//减去1.6V防止溢出*******************if(AD_wData[0]<0xC0&& AD_wData[1]<0xC0&&AD_wData[2]<0xC0&&AD_wData[3]<0xC0&&AD_wData[4]<0xC0&&AD_wData[5]<0xC0&&AD_wData[6]<0xC0&&AD_wD ata[7]<0xC0&&AD_wData[8]<0xC0){if(sum2[0]<0xC0&&sum2[1]<0xC0&&sum2[2]<0xC0&&sum2[3]<0xC0&&sum2[4]<0xC0&&sum2[5]<0xC0&&sum2[6]<0xC0&&sum2[7]<0xD0){fla=1;if(flagg0==1){for(i=0;i<0xFF;i++);PWM_Init1(1140,u1,200);flagk1=1;flagkk2=0;for(;;){if(AD_wData[4]>0xB0||AD_wData[5]>0xB0||AD_wData[6]>0xB0|| AD_wData[7]>0xB0||AD_wData[8]>0xB0){flagg0=0;break;}}}else if(flagg0==2){for(i=0;i<0xFF;i++);PWM_Init1(1860,u1,200);flagk1=0;flagkk2=1;for(;;)if(AD_wData[0]>0xB0||AD_wData[1]>0xB0||AD_wData[2]>0xB0||AD_wData[3]>0xB0||AD_wData[4]>0xB0){flagg0=0;break;}}}else{}}else{if(s[0]-(avrg0[0]-0x13)<0x40 &&s[1]-(avrg0[1]-0x13)<0x40 &&s[2]-(avrg0[2]-0x13)<0x40 && s[3]-(avrg0[3]-0x13)<0x40 &&s[4]-(avrg0[4]-0x13)<0x40 && s[5]-(avrg0[5]-0x13)<0x40 &&s[6]-(avrg0[6]-0x13)<0x40 && s[7]-(avrg0[7]-0x13)<0x40 &&s[8]-(avrg0[8]-0x13)<0x40)///////////注意调整该值36***************{/* if(PORTA_BIT6!=0||PORTA_BIT7!=0){if(PORTA_BIT6!=0&&PORTA_BIT7==0)PWM_Init1(1900,200,1);else if(PORTA_BIT7!=0&&PORTA_BIT6==0)PWM_Init1(1100,200,1);}*/}else{k=max(sum2[0],sum2[1],sum2[2],sum2[3],sum2[4],sum2[5],sum2[ 6],sum2[7]);//谁两和最大,黑道就在谁两之间if(k==sum2[0]){p=0;flagg0=2;if(fla==1)control_11();else if(fla==0) control_1();}else{if(k==sum2[1]){p=0;p1=0;fla=0;control_2(s[1],s[2],ss[1],ss[2],cha[1],cha[2],avrg0[1],avrg 0[2]);}else{if(k==sum2[2]){p=0;p1=0;fla=0;control_3(s[2],s[3],ss[2],ss[3],cha[2],cha[3],avrg0[2],avrg 0[3]);}else{if(k==sum2[3]){p=0;p1=0;fla=0;control_4(s[3],s[4],ss[3],ss[4],cha[3],cha[4],avrg0[3],avrg 0[4]);}else{if(k==sum2[4]){fla=0;p1=0;control_5(s[4],s[5],ss[4],ss[5],cha[4],cha[5],avrg0[4],avrg 0[5]);}else{if(k==sum2[5]){fla=0;p1=0;control_6(s[5],s[6],ss[5],ss[6],cha[5],cha[6],avrg0[5],avrg 0[6]);}else{if(k==sum2[6]){p=0;p1=0;fla=0;control_7(s[6],s[7],ss[6],ss[7],cha[6],cha[7],avrg0[6],avrg 0[7]);}else{if(k==sum2[7]){p=0;flagg0=1;if(fla==0)control_8(); elseif(fla==1)control_88(); } else{}}}}}}}}}}}}。
飞思卡尔单片机S12使用方法及程序单片机简介: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口上去。
基于飞思卡尔MC9S12XEP的SPI程序#defineSPI_GLOBALS#include\#defineWrite_To_FlahDataSize15taticuint8_tDummy;//选中flahvoidSPICSLow(uint8_tChip){if(Chip==0){SPI_FLASH1_CS_LOW();//选中flah1}ele{SPI_FLASH2_CS_LOW();//选中flah2}}//不选voidSPICSHigh(uint8_tChip){if(Chip==0){SPI_FLASH1_CS_HIGH();//不选中flah1}ele{SPI_FLASH2_CS_HIGH();//不选中flah2}}//flah写使能voidSPIWriteEnable(uint8_tChip){//flah写除能voidSPIWriteDiable(uint8_tChip){SPICSLow(Chip);//bringthechoenchip'CSpindown//SPI初始化voidSPIInit(void){DDRP_DDRP0=1;DDRP_DDRP1=1;DDRP_DDRP2=1;DDRP_DDRP3=1;SPI_WP1_OFF();SPI_WP2_OFF();SPI_FLASH1_CS_HIGH();SPI_FLASH2_CS_HIGH();SPI2BR=(0<<4)|(0);//(0+1)某2^(0+1)=2,20M/2=10MSPI2CR1=0某50;//主机模式}//SPI读flah的IDSPI_E某Tuint16_tSPIReadID(uint8_tChip){uint16_tID;SPICSLow(Chip);//bringthechoenchip'CSpindownDummy=SPIReadWriteByte(SPI2,0某00);//writeAddr[16:23]//写24位地址Dummy=SPIReadWriteByte(SPI2,0某00);//writeAddr[8:15]Dummy=SPIReadWriteByte(SPI2,0某00);//writeAddr[0:7]((uint8_t某)&ID)[0]=SPIReadWriteByte(SPI2,SPI_CMD_DUMMY);//manufacturerID ((uint8_t某)&ID)[1]=SPIReadWriteByte(SPI2,SPI_CMD_DUMMY);//deviceIDreturnID;//returntheIDvalue}//SPI读flah状态uint8_tSPIReadSta(uint8_tChip){uint8_tSta;SPICSLow(Chip);//bringthechoenchip'CSpindownSta=SPIReadWriteByte(SPI2,SPI_CMD_DUMMY);//tatuSPICSHigh(Chip);//bringthechoenchip'CSpinhighreturnSta;//returnthetatuvalue}//等待芯片空闲(在执行Byte-Program,Sector-Erae,Block-Erae,Chip-Erae操作后voidSPIWaitBuy(uint8_tChip){SPICSLow(Chip);///----------------------------------------------------------------------------------------------------------//Function:SPIFlah初始化//Param://Return://note///----------------------------------------------------------------------------------------------------------SPI_E某TvoidSPIFlahInit(void){uint8_ti;uint16_tID;SPIInit();//memet(SPI_Flah_Info,0,izeof(SPI_Flah_Info));//for(i=0;i<SP I_MA某_CHIPS;i++){ID=SPIReadID(i);SPI_Flah_Info[i].DeviceID=ID;SPI_Flah_Info[i].Size=(uint32_t)8某1024某1024;SPI_Flah_Info[i].SectorSize=4某1024;SPI_Flah_Info[i].SectorPage=16;SPI_Flah_Info[i].BlockSize=(uint32_t)64某1024;SPI_Flah_Info[i].Block=128;SPI_Flah_Info[i].PageSize=256;SP I_Flah_Info[i].Page=65536;}}/某--------------------------------------------------------------------------------------------------------SPI收发送函数----------------------------------------------------------------------------------------------------------某/SPI_E某Tuint8_tSPIReadWriteByte(uint8_tSPI,uint8_tData){if(SPIcaeSPI0:while(SPI0SR_SPTEF==0);SPI0DRL=Data;while(SPI0SR_SPIF==0);returnSPI0DRL;break;caeSPI2:while(SPI2SR_SPTEF==0);SPI2DRL=Data;while(SPI2SR_SPIF==0);returnSPI2DRL;break;}}///----------------------------------------------------------------------------------------------------------//Function:把Chip号芯片的Adre位置开始Len长度的数据读取到Buf中//Param://Return://note///----------------------------------------------------------------------------------------------------------SPI_E某TvoidSPIRead(uint8_tChip,uint32_tAddre,uint8_t某Buf,uint32_tLen){uint32_ti;SPIWaitBuy(Chip);//判忙SPICSLow(Chip);//bringthechoenchip'CSpindownDummy=SPIReadWriteByte(SPI2,((uint8_t某)&Addre)[1]);//writeAddr[8:15]某)&Addre)[2]);//writeAddr[0:7]for(i=0;i<Len;i+=1){Buf[i]=SPIReadWriteByte(SPI2,SPI_CMD_DUMMY);//readdata}SPICSHigh(Chip);//bringthechoenchip'CSpinhigh}///----------------------------------------------------------------------------------------------------------//Function:向chip号芯片的Addre位置开始的区域写入长度为Len 的Buf内容//Param://Return://note///----------------------------------------------------------------------------------------------------------SPI_E某TvoidSPIWritePage(uint8_tChip,uint32_tAddre,uint8_tBuf[],uint32_ tLen){uint8_ti;SPIWriteEnable(Chip);SPICSLow(Chip);//bringthechoenchip'CSpindownDummy=SPIReadWriteByte(SPI2,((uint8_t某)&Addre)[0]);//write Addr[16:23]Dummy=SPIReadWriteByte(SPI2,((uint8_t某)&Addre)[1]);//writeAddr[8:15]某)&Addre)[2]);//writeAddr[0:7]for(i=0;iDummy=SPIReadWriteByte(SPI2,Buf[i]);//writethedatatobeent} SPICSHigh(Chip);//bringthechoenchip'CSpinhighSPIWaitBuy(Chip );//判忙}///----------------------------------------------------------------------------------------------------------//Function:擦除flah一个ector//Param://Return://note///----------------------------------------------------------------------------------------------------------SPI_E某TvoidSPIEraeSector(uint8_tChip,uint32_tAddre){SPIWriteEnable(Chip);//writeenableSPIWaitBuy(Chip);//判忙SPICSLow(Chip);//bringthechoenchip'CSpindownDummy=SPIReadWriteByte(SPI2,SPI_CMD_4K_ERASE);//write4K_Erae Dummy=SPIReadWriteByte(SPI2,((uint8_t某)&Addre)[1]);//writeAddr[8:15]Dummy=SPIReadWriteByte(SPI2,((uint8_t某)&Addre)[2]);//writeAddr[0:7]SPICSHigh(Chip);//bringthechoenchip'CSpinhighSPIWriteDiable(Chip);SPIWaitBuy(Chip);//判忙}///----------------------------------------------------------------------------------------------------------//Function:擦除flah一个block//Param://Return://note///----------------------------------------------------------------------------------------------------------SPI_E某TvoidSPIEraeBlock(uint8_tChip,uint32_tAddre){SPIWriteEnable(Chip);SPIWaitBuy(Chip);//判忙SPICSLow(Chip);//bringthechoenchip'CSpindownDummy=SPIReadWriteByte(SPI2,((uint8_t某)&Addre)[0]);//writeAddr[16:23]Dummy=SPIReadWriteByte(SPI2,((uint8_t某)&Addre)[1]);//writeAddr[8:15]Dummy=SPIReadWriteByte(SPI2,((uint8_t某)&Addre)[2]);//writeAddr[0:7]SPICSHigh(Chip);//bringthechoenchip'CSpinhighSPIWriteDiable(Chip);SPIWaitBuy(Chip);//判忙}///----------------------------------------------------------------------------------------------------------//Function:擦除flah整片芯片//Param://Return://note///----------------------------------------------------------------------------------------------------------SPI_E某TvoidSPIEraeChip(uint8_tChip){SPIWriteEnable(Chip);SPIWaitBuy(Chip);//判忙SPICSLow(Chip);Dummy=SPIReadWriteByte(SPI2,SPI_CMD_CHIP_ERASE);SPICSHigh(Chip);SPIWaitBuy(Chip);//判忙SPIWriteDiable(Chip);}/某----------------------------------------------------------------------------------------------------------向SPI_FlahBuf 里面写入数据------------------------------------------------------------------------------------------------------------某///SPI_E某TSPIWriteToBuf/某----------------------------------------------------------------------------------------------------------向SPI_FlahBuf 里面写入数据------------------------------------------------------------------------------------------------------------某/SPI_E某TvoidSPIWriteToBuf(uint8_tarray[],uint8_tarray_len){uint8_ti;for(i=0;i<array_len;i++)SPI_FlahBuf[i]=array[i];SPI2CR1_SPIE=1;//给SPI缓冲区写完数据,打开中断,将数据写入到Flah里面。
飞思卡尔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,然后通过控制寄存器发出转换命令,即可实现转换。
#define RS485_GLOBALS#include "RS485.h"#include "clk.h"RS485_EXT void RS485_QUE_Int(){RS485_RXQUE_SCI1.Rear=0;RS485_RXQUE_SCI1.Front=0;RS485_RXQUE_SCI0.Rear=0;RS485_RXQUE_SCI0.Front=0;RS485_TXQUE_SCI0.Front=0;RS485_TXQUE_SCI0.Rear=0;RS485_TXQUE_SCI1.Front=0;RS485_TXQUE_SCI1.Rear=0;RS485_SCI1_Status=1;RS485_SCI0_Status=1;rs485Init( SCI0);rs485Init( SCI1);}/////////////////////////////////////////////////////////////////////////////// ///////RS485_EXT void rs485Init(uint8_t SCI){if(SCI<SCIX){switch(SCI){case SCI0:SCI0BDH = SCI0Baud_val>>8;SCI0BDL = SCI0Baud_val;SCI0CR1 = 0x00; //8个数据位无校验位SCI0CR2 = (0<<5) | (1<<3) | (1<<2);//SCI2CRC2 第5,3,2位置1 RIE TE RE break;case SCI1:SCI1BDH = SCI1Baud_val>>8;SCI1BDL = SCI1Baud_val;SCI1CR1 = 0x00; //8个数据位无校验位SCI1CR2 = (0<<5) | (1<<3) | (1<<2);//SCI4CRC2 第5,3,2位置1 RIE TE RE break;}}}/////////////////////////////////////////////////////////////////////////////// /////////功能:RS485_0发射、接收切换函数,Tx_Rx为Rx时,开启接收功能,为Tx时,开启发送功能//参数定义:Tx_Rx是用来对函数功能切换的,使输出脚电平的不同,来控制硬件的功能切换///////////////////////////////////////////////////////////////////////////////////// ////////////*/RS485_EXT void rs485_TxOrRx(uint8_t SCI,uint8_t Tx_Rx){DDR1AD0_DDR1AD07=1;DDR0AD0_DDR0AD07=1;if(SCI<SCIX){switch(SCI){case SCI0: if(Tx_Rx==1)PT1AD0_PT1AD07=1;elsePT1AD0_PT1AD07=0;break;case SCI1: if(Tx_Rx==1)PT0AD0_PT0AD07=1;elsePT0AD0_PT0AD07=0;break;}}}/*------------------------------------------------------------------------------------------功能:RS485发射函数参数定义:SCI用来选择RS485 1和0模块,array[]是要发射的数据数组名,也就是首地址。
#define RS232_GLOBALS#include "RS232.h"/*-------------------------------------------------------------------------------RS232_SCI2初始化---------------------------------------------------------------------------------*/RS232_EXT void RS232_Init(void){RS232_TXQUE_SCI2.Front=0;RS232_TXQUE_SCI2.Rear=0;RS232_RXQUE_SCI2.Front=0;RS232_RXQUE_SCI2.Rear=0;SCIInit( SCI2); //RS232波特率初始化}/*-------------------------------------------------------------------------------RS232_SCI2 选择发送数据方式,是查询发送还是中断发送---------------------------------------------------------------------------------*/RS232_EXT void RS232PutStr(uint8_t array[],uint8_t arrayLen,uint8_t Type) {uint8_t m,i ;if(Type){ for(i=0;i<arrayLen;i++)RS232_TXBuf_Write( array[i]);SCI2CR2_TIE=1;}elsefor(m=0;m<arrayLen;m++){while(!SCI2SR1_TDRE);SCI2DRL = array[m];}}/*------------------------------------------------------------------------------RS232_SCI2 向发送缓冲区写入数据函数--------------------------------------------------------------------------------*/RS232_EXT void RS232_TXBuf_Write(uint8_t TXData){uint8_t DataTemp;DataTemp = (uint8_t)((RS232_TXQUE_SCI2.Rear+1)% RS232_TXQUE_LEN);if(RS232_TXQUE_SCI2.Front!=DataTemp) //判断队列是否满,若不满,可以入列送出数据{RS232_TXQUE_SCI2.RS232_Bufs[ RS232_TXQUE_SCI2.Rear].Data = TXData; RS232_TXQUE_SCI2.Rear = DataTemp;}else{SCI2CR2_TIE=1;}}/*----------------------------------------------------------------------------------RS232_SCI2 读取接收缓存区里面的数据-----------------------------------------------------------------------------------*/RS232_EXT uint8_t RS232_RXBuf_Read(){uint8_t DataTemp;if( RS232_RXQUE_SCI2.Front!=RS232_RXQUE_SCI2.Rear) //缓冲区不空,可以读出数据{DataTemp = RS232_RXQUE_SCI2.RS232_Bufs[ RS232_RXQUE_SCI2.Front].Data;RS232_RXQUE_SCI2.Front=(uint8_t)((RS232_RXQUE_SCI2.Front+1)%RS232_TXQUE_LEN);return DataTemp;}else{ return 0xff; } //返回的数据无意义,为0xff,}/*--------------------------------------------------------------------------------RS232_SCI2 中断函数-----------------------------------------------------------------------------------*/RS232_EXT void RS232_SCI2_Interrupt(void){uint8_t Dummy,TDRE_flag,RDRF_flag,NextPointer;Dummy = SCI2SR1;TDRE_flag = 0x80&Dummy;RDRF_flag = 0x20&Dummy;if(RDRF_flag){NextPointer = (uint8_t)((RS232_RXQUE_SCI2.Rear+1)% RS232_TXQUE_LEN);if(RS232_RXQUE_SCI2.Front!= NextPointer ) //如果不满可以入列{RS232_RXQUE_SCI2.RS232_Bufs[ RS232_RXQUE_SCI2.Rear].Data= SCI2DRL;RS232_RXQUE_SCI2.Rear = NextPointer;}}if(TDRE_flag){if(RS232_TXQUE_SCI2.Front!=RS232_TXQUE_SCI2.Rear) //有新数据,则继续发送{SCI2DRL= RS232_TXQUE_SCI2.RS232_Bufs[ RS232_TXQUE_SCI2.Front].Data;RS232_TXQUE_SCI2.Front = (uint8_t)((RS232_TXQUE_SCI2.Front+1)%RS232_TXQUE_LEN);}else{ SCI2CR2_TIE=0;}}}/*---------------------------------------------------------------------------------发送数据函数,1.若果选择查询发送,则会将对应的数组以查询的方式发送出去2.如果选择中断的发送方式,则先将相应的数组写入到缓冲区,开启中断,则数据通过中断函数发送出去该函数已封装好,只需填写要发送的数组名,数组长度,发送方式,即可发送-----------------------------------------------------------------------------------*/RS232_EXT void RS232_TXData( uint8_t TXData[],uint8_t TXData_LEN,uint8_t Type){RS232PutStr(TXData,TXData_LEN,Type);}/*-----------------------------------------------------------------------------------接收数据函数,将接受缓冲区的数据写入到指定数组中。