飞思卡尔s12单片机-用C语言开发应用程序
飞思卡尔单片机S12使用方法及程序

飞思卡尔单片机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口上去。
C语言实现控制电机加减速正反转(飞思卡尔C代码)

C语言实现控制电机加减速正反转(飞思卡尔C代码)用单片机控制直流电动机的正反转、加减速的程序如何用C语言写参考一下这个例子吧。
#include#defineucharunignedchar#defineuintunignedintbitPW1=P2^0;bitPW2=P2^1;//控制电机的两个输入bitaccelerate=P2^2;//调速按键bittop=P2^3;//停止按键bitleft=P2^4;//左转按键bitright=P2^5;//右转按键#defineright_turnPW1=0;PW2=1//顺时针转动#defineleft_turnPW1=1;PW2=0//逆向转动#defineend_turnPW1=1;PW2=1//停转uintt0=25000,t1=25000;//初始时占空比为50%uinta=25000;//设置定时器装载初值25m设定频率为20Hzucharflag=1;//此标志用于选择不同的装载初值uchardflag;//左右转标志ucharcount;//用来标志速度档位voidkeycan();//键盘扫描voiddelay(ucharz);voidadjut_peed();//通过调整占空比来调整速度//某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某//voidmain(){keycan();//不断扫描键盘程序,以便及时作出相应的响应}}if(flag){flag=0;end_turn;a=t0;//t0的大小决定着低电平延续时间TH0=(65536-a)/256;TL0=(65536-a)%6;//重装载初值}ele{flag=1;//这个标志起到交替输出高低电平的作用if(dflag==0){right_turn;//右转}ele{left_turn;//左转}a=t1;//t1的大小决定着高电平延续时间TH0=(65536-a)/256;TL0=(65536-a)%6;//重装载初值}}TMOD=0某01;//工作方式寄存器软件起动定时器定时器功能方式1定时器0TH0=(65536-a)/256;TL0=(65536-a)%6;//装载初值ET0=1;//开启定时器中断使能EA=1;//开启总中断TR0=0;}//某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某//voiddelay(ucharz)//在12M下延时z毫秒{ uint某,y;for(某=z;某>0;某--)for(y=110;y>0;y--);}//某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某//voidkeycan(){if(top==0){TR0=0;//关闭定时器0即可停止转动end_turn;} if(left==0){TR0=1;dflag=1;//转向标志置位则左转}if(right==0){TR0=1;dflag=0;//转向标志复位则右转}if(accelerate==0){delay(5);//延时消抖if(accelerate==0){ while(accelerate==0);//等待松手count++;if(count==1){t0=20000;t1=30000;//占空比为百分之60}if(count==2){t0=15000;t1=35000;//占空比为百分之70}if(count==3){t0=10000;t1=40000;//占空比为百分之80}if(count==4){t0=5000;t1=45000;//占空比为百分之90}if(count==5){count=0;}}}}功能特点:1)总线速度高达40MHz,CAN总线:3个1Mbp的CAN总线,兼容CAN2.0A/B;2)128KB程序Flah和8KBDataFlah,用于实现程序和数据存储,均带有错误校正码(ECC);3)可配置A/D:16通道模数转换器;可选8位10位和12位精度,3μ的转换时间4)内嵌MSCAN模块用于CAN节点应用,内嵌支持LIN协议的增强型SIC模块和SPI模块;5)4通道16位计数器,CRG时钟和复位发生器:锁相环、看门狗、实时中断;增强型捕捉定时器;6)出色的低功耗特性,带有中断唤醒功能的10,实现唤醒休眠系统的功能;7)通道PWM:8位8通道或16位4通道PWM,易于实现电机控制。
pwm(飞思卡尔单片机)

#include "derivative.h" /* derivative-specific definitions */
/*************************************************************/
REFDV = 0x01; //时钟分频寄存器
//锁相环产生的时钟频率f=2*foscclk*(SYNR+1)/(REFDV+1)
//对于S12DG128 16MHz外部晶体振荡器,总线时钟为24MHz
//片内系统时钟为48MHz
while((CRGFLG & 0x08) !=0x08); /*等待锁相环频率锁定*/
PWMPER01 = 5000; //通道01的周期为4Hz
PWMPER23 = 5000; //通道23的周期为1Hz
PWMDTY01 = 3500; //通道01的占空比为70%
PWMDTY23 = 1500; //通道23的占空比为70%
PWME_PWME1 = 1; //使能通道01
PWME_PWME3 = 1; //使能通道23
}
void main(void) {
DisableInterrupts;
MCUInit();
init_pwm();
DDRB=1;
PORTB=1;
EnableInterrupts;
foபைடு நூலகம்(;;)
{
}
}
void init_pwm(void)
{
PWMCTL_CON01= 1; //联结通道0,1为16位的PWM
FreeScale_HCS12系列单片机教程(dg128)

HCS12微控制器系列教程---第一讲:PWM 模块介绍该教程以MC9S12DG128单片机为核心进行讲解,全面阐释该16位单片机资源。
本文为第一讲,开始介绍S12 MCU的PWM模块。
PWM 调制波有8 个输出通道,每一个输出通道都可以独立的进行输出。
每一个输出通道都有一,一个周期控制寄存器和两个可供选择的时钟源。
每一个PWM 输出个精确的计数器(计算脉冲的个数)通道都能调制出占空比从0—100% 变化的波形。
PWM 的主要特点有:1、它有8 个独立的输出通道,并且通过编程可控制其输出波形的周期。
2、每一个输出通道都有一个精确的计数器。
3、每一个通道的PWM 输出使能都可以由编程来控制。
4、PWM输出波形的翻转控制可以通过编程来实现。
5、周期和脉宽可以被双缓冲。
当通道关闭或PWM计数器为0时,改变周期和脉宽才起作用。
6、8 字节或16 字节的通道协议。
,他们提供了一个宽范围的时钟频率。
7、有4 个时钟源可供选择(A、SA、B、SB)8、通过编程可以实现希望的时钟周期。
9、具有遇到紧急情况关闭程序的功能。
10、每一个通道都可以通过编程实现左对齐输出还是居中对齐输出。
HCS12微控制器系列教程---第二讲:PWM 寄存器简介1、PWM启动寄存器PWMEPWME 寄存器每一位如图1所示:复位默认值:0000 0000B图1 PWME 寄存器每一个PWM 的输出通道都有一个使能位PWMEx 。
它相当于一个开关,用来启动和关闭相应通道的PWM 波形输出。
当任意的PWMEx 位置1,则相关的PWM输出通道就立刻可用。
用法:PWME7=1 --- 通道7 可对外输出波形PWME7=0 --- 通道7 不能对外输出波形注意:在通道使能后所输出的第一个波形可能是不规则的。
当输出通道工作在串联模式时(PWMCTL寄存器中的CONxx置1),那么)使能相应的16位PWM 输出通道是由PWMEx的高位控制的,例如:设置PWMCTL_CON01 = 1,通道0、1级联,形成一个16位PWM 通道,由通道1 的使能位控制PWM 的输出。
2011年飞思卡尔比赛程序

#include <hidef.h> /* common defines and macros */#include <mc9s12dg128.h> /* derivative information //引用头文件,通过该头文件将单片机的各寄存器转换为相对应的C语言的变量名*/#pragma LINK_INFO DERIVATIVE "mc9s12dg128b"#define mid_direction 147 //设置舵机中间位置的占空比#define right_direction 0 //设置直线路程时的相对中间位置的变化量#define micro_direction 12 //设置转小弯时舵机相对中间位置的变化量#define deep_direction 19 //设置转大弯时舵机相对中间位置的变化量#define emergence_direction 22 //设置紧急情况时舵机转向#define direct_speed 14 //设置直线时输出到电机的占空比从而控制电机转速#define micro_speed 13 //设置小弯时电机转速#define deep_speed 11 //设置大弯时电机转速#define emergence_speed 10 //设置紧急情况时电机转速#define inter 5#define inter1 500 //通过设置该参数数值来调节每次采集轮速传感的脉冲时间#define speed_keep 0.4 //为轮速的比例因子,因使用效果不好最后取消使用#define speed_kd 0.1#define kp 0.5//#define kd 1.3 //下列的全局变量的设定,是为了在小车冲出赛道后仍能记住返回而设int turn_symbol; //转向标志,在信号分析程序中设置1时为向右转为-1时向左转float memory_direction; //记忆上次转向unsigned char signal;int error; //定义转向本次与中间位置的偏差int last_error; //定义上次转向与中间位置的偏差int mem_error; //记忆上次转向偏差int speed;int speed1;float kd;float speed_error;float speed_last_error;int speed_back; //轮速反回脉冲数int stop_symbol; // 停车标志int flag;void PLL_init(void) // 系统时钟的初始化,因当时摸索欠考虑,时钟初始化比较乱,需要改进{CLKSEL_PLLSEL=0; //选定外部时钟,为1时选择锁相环时钟时钟选择寄存器初始化CLKSEL=0 ; //选择外部晶振为时钟源PLLCTL_PLLON=0; //锁相环电路禁止;PLLCTL_PRE=1; //实时中断允许PLLCTL_PCE=1; //允许看门狗PLLCTL_AUTO=1; //选择高频宽带控制PLLCTL_SCME=1; //探测到外部时钟失效时产生自给时钟信号SYNR=8; //时钟合成寄存器初始化REFDV=0X07; //时钟分频寄存器初始化与上句为做实验时确定的参数与理论参数有差距,可重新设置//CLKSEL_PLLSEL=1 ; //选定锁相环时钟此句被注解掉PLLCTL_CME=1; //时钟监控允许锁相环控制寄存器初始化PLLCTL_PLLON=1;while(!CRGFLG_LOCK);//循环直到该位为1即时钟频率已稳定,CLKSEL_PLLSEL=1; //选定锁相环时钟}void PORTAB_init(void) //信号输入输出口的设置,较简单{DDRA=0X00; //设置A口输入 DDR寄存器置0为输入,置1为输出DDRB=0XFF;//设置B口为输出,作为信号指示PORTB=0X00;//初始化时设置为全亮,0亮1灭}void PWM_init(void) //脉宽调制模块的初始化。
飞思卡尔智能车程序代码

#define flag 1;
extern uchar cflag;
extern int i,j,m,n;
extern byte cs[40][60];
/*-----------------------*/
/*-------初始化----------*/
void InputInit(){
#pragma TRAP_PROC
void IRQ_ISR()
{
TIE_C1I=1; ;
//DDRB=0XFF;
//PORTB=0XF0;
//while(1);
i=0;
j=0;
}
#pragma CODE_SEG DEFAULT
#pragma CODE_SEG NON_BANKED
#pragma TRAP_PROC
TIE_C1I=0 ; //channel 0 interrupt DISable
TIOS_IOS1=0 ; //channel 0 input capture
TCTL4_EDG1A=1;
TCTL4_EDG1B=0;
}
/*-----------------------*/
/*--中断初始化--------------------*/
void init_IRQ() {
INTCR_IRQE=1; // IRQ select edge sensitive only
INTCR_IRQEN=1; // external IRQ enable
}
/*------ADT初始化--------------*/
void ADCInit(void)
void linenihe(void);
飞思卡尔MC9S12XEP芯片的CAN总线代码

#define CAN_GLOBALS#include "can.h"void EEC1_Process(uint8_t OutPtr, uint8_t InPtr);void EEC2_Process(uint8_t OutPtr, uint8_t InPtr);void EEC3_Process(uint8_t OutPtr, uint8_t InPtr);void ET1_Process(uint8_t OutPtr, uint8_t InPtr);void CCVS_Process(uint8_t OutPtr, uint8_t InPtr);void LFE_Process(uint8_t OutPtr, uint8_t InPtr);void AMB_Process(uint8_t OutPtr, uint8_t InPtr);void IC1_Process(uint8_t OutPtr, uint8_t InPtr);void VEP1_Process(uint8_t OutPtr, uint8_t InPtr);void EFL_P1_Process(uint8_t OutPtr, uint8_t InPtr);void LFC_Process(uint8_t OutPtr, uint8_t InPtr);void Digit2Ascii1(uint32_t Digit, uint8_t InPtr); //一位小数void Digit2Ascii0(uint32_t Digit, uint8_t InPtr); //数字转化为ASCII码 0位小数void Digit2AsciiPos0(uint32_t Digit, uint8_t InPtr); //数字转化为ASCII码 0位小数负数uint8_t *Result;HMI_Text_Dis_tPtr HMI_Text_DisPtr;///----------------------------------------------------------------------------------------------------------//Function://Param://Return://note///----------------------------------------------------------------------------------------------------------void CANFilterInit(uint8_t CAN){if(CAN<CANS){switch(CAN){case CAN0:CAN0IDAR0 = 0xFF;CAN0IDAR1 = 0xFF; CAN0IDAR2 = 0xFF; CAN0IDAR3 = 0xFF; CAN0IDMR0 = 0xFF; CAN0IDMR1 = 0xFF; CAN0IDMR2 = 0xFF; CAN0IDMR3 = 0xFF; CAN0IDAR4 = 0xFF; CAN0IDAR5 = 0xFF; CAN0IDAR6 = 0xFF; CAN0IDAR7 = 0xFF; CAN0IDMR4 = 0xFF; CAN0IDMR5 = 0xFF; CAN0IDMR6 = 0xFF; CAN0IDMR7 = 0xFF; break;case CAN1:CAN1IDAR0 = 0xFF; CAN1IDAR1 = 0xFF; CAN1IDAR2 = 0xFF; CAN1IDAR3 = 0xFF; CAN1IDMR0 = 0xFF; CAN1IDMR1 = 0xFF; CAN1IDMR2 = 0xFF; CAN1IDMR3 = 0xFF; CAN1IDAR4 = 0xFF; CAN1IDAR5 = 0xFF; CAN1IDAR6 = 0xFF; CAN1IDAR7 = 0xFF; CAN1IDMR4 = 0xFF; CAN1IDMR5 = 0xFF; CAN1IDMR6 = 0xFF; CAN1IDMR7 = 0xFF; break;}}}/*--------------------------------------------------------------------------------------------------------Function:Param:Return:note----------------------------------------------------------------------------------------------------------*/void CANRxQueInit(void){CAN_RxQue.Front = 0;CAN_RxQue.Rear = 0;memset(&CAN_RxQue, 0, sizeof(CAN_RxQue));}/*--------------------------------------------------------------------------------------------------------Function: CAN0 CAN1初始化Param:Return:note----------------------------------------------------------------------------------------------------------*/CAN_EXT void CANInit(uint8_t CAN){if(CAN<CANS){switch(CAN){case CAN0:CAN0CTL1_CANE = 1; //使能CAN模块CAN0CTL1_LISTEN = 0; //除能监听模式CAN0BTR0 = CAN0BTR0_Val; //设置波特率CAN0BTR1 = CAN0BTR1_Val;CANFilterInit(CAN0); //设置验收、屏蔽滤波器CAN0CTL0_INITRQ = 0; //请求退出初始化while(CAN0CTL1_INITAK == 1){ //请求处理ing _asm(nop);}while(CAN0CTL0_SYNCH == 0){_asm(nop);}CAN0RFLG = 0xC3; //清除接收相关标志位CANRxQueInit(); //CAN中断接收队列CAN0RIER_RXFIE = 1; //接收中断允许break;case CAN1:CAN1CTL1_CANE = 1; //使能CAN模块CAN1CTL1_LISTEN = 0; //除能监听模式CAN1BTR0 = CAN1BTR0_Val; //设置波特率CAN1BTR1 = CAN1BTR1_Val;CANFilterInit(CAN1); //设置验收、屏蔽滤波器CAN1CTL0_INITRQ = 0; //请求退出初始化while(CAN1CTL1_INITAK == 1){ //请求处理ing _asm(nop);}while(CAN1CTL0_SYNCH == 0){_asm(nop);}CAN1RFLG = 0xC3; //清除接收相关标志位CANRxQueInit(); //CAN中断接收队列CAN1RIER_RXFIE = 1; //接收中断允许break;}}}/*----------------------------------------------------------------------------------------------------------Function:存储并显示把CAN_RxQue 队列里的数据存放到 FLASH 中,某些数据再存到HMI_Text_Dis_Que 队列里进行显示其中 CAN_RxQue 的ID转换为 PGNTmp 再转换为 HMI_Text_Dis_Que 显示的位置CAN_RxQue 的数据即 HMI_Text_Dis_Que 的数据起始帧命令帧终止帧都已包含Param:Return:note----------------------------------------------------------------------------------------------------------*/CAN_EXT void CANRxQueToProcess(void){ID_tPtr IDPtr;uint32_t PGNTmp;while(CAN_RxQue.Front!= CAN_RxQue.Rear) //源队列未空,可出列{IDPtr = &(CAN_RxQue.PDUs[CAN_RxQue.Front].Bits.ID); //指向出列项ID 域PGNTmp = 0;PGNTmp |= (uint8_t)(IDPtr->Bits.DP | IDPtr->Bits.R<<1);//析取DP和RPGNTmp <<= 8;PGNTmp |= (uint8_t)(IDPtr->Bits.PF0 | IDPtr->Bits.PF1<<2 | IDPtr->Bits.PF2<<5); //析取PFPGNTmp <<= 8;PGNTmp |= (uint8_t)(IDPtr->Bits.PS0 | IDPtr->Bits.PS1<<7);//析取PSif(PGNTmp == (uint16_t)PGN_FAULT_MEMORY){FAULT_flag = 1;}else{FAULT_flag = 0;}switch(PGNTmp){case (uint16_t)PGN_EEC1:EEC1_Process(CAN_RxQue.Front, HMI_Text_Dis_Que.Rear); break;case (uint16_t)PGN_EEC2:EEC2_Process(CAN_RxQue.Front, HMI_Text_Dis_Que.Rear); break;case (uint16_t)PGN_EEC3:EEC3_Process(CAN_RxQue.Front, HMI_Text_Dis_Que.Rear); break;case (uint16_t)PGN_AMB:AMB_Process(CAN_RxQue.Front, HMI_Text_Dis_Que.Rear); break;case (uint16_t)PGN_CCVS:CCVS_Process(CAN_RxQue.Front, HMI_Text_Dis_Que.Rear);break;case (uint16_t)PGN_ET1:ET1_Process(CAN_RxQue.Front, HMI_Text_Dis_Que.Rear); break;case (uint16_t)PGN_LFE:LFE_Process(CAN_RxQue.Front, HMI_Text_Dis_Que.Rear); break;case (uint16_t)PGN_EFL_P1:EFL_P1_Process(CAN_RxQue.Front, HMI_Text_Dis_Que.Rear); break;case (uint16_t)PGN_IC1:IC1_Process(CAN_RxQue.Front, HMI_Text_Dis_Que.Rear); break;case (uint16_t)PGN_VEP1:VEP1_Process(CAN_RxQue.Front, HMI_Text_Dis_Que.Rear); break;case (uint16_t)PGN_LFC: // 时间太大目前只能计算两个字节的LFC_Process(CAN_RxQue.Front, HMI_Text_Dis_Que.Rear);break;case (uint16_t)PGN_FAULT_MEMORY:FAULT_MEMORY_Process(CAN_RxQue.Front, HMI_Text_Dis_Que.Rear, 0, 0); //为了方便触摸屏看故障类型上下条时使用break;default:break;}CAN_RxQue.Front = (uint8_t)(CAN_RxQue.Front+1)%CAN_RXQUE_LEN;//出列一项}CANRxQueInit();}///----------------------------------------------------------------------------------------------------------//Function://Param://Return://note///----------------------------------------------------------------------------------------------------------void EEC1_Process(uint8_t OutPtr, uint8_t InPtr){uint32_t engspeed;uint32_t actualengtorque;eec1 = (EEC1_t *)CAN_RxQue.PDUs[OutPtr].Bits.DataField;engspeed = (((uint32_t)swab16(eec1->EngSpeed))*12) +(((uint32_t)swab16(eec1->EngSpeed))>>1);actualengtorque = ((uint32_t)(eec1->ActualEngTorque)) * 100;if(HMI_Text_Dis_Que.Front !=(HMI_Text_Dis_Que.Rear+1)%HMI_TEXTDIS_QUELEN) {HMI_Text_DisPtr = HMI_Text_Dis_Que.HMI_Text_Dis +HMI_Text_Dis_Que.Rear;HMI_Text_DisPtr->CMD_Start = HMI_CMD_START;HMI_Text_DisPtr->CMD_Type = HMI_CMD_TextDIS_ASCII;HMI_Text_DisPtr->Start_Point.x = 145;HMI_Text_DisPtr->Start_Point.y = 150;Digit2Ascii0(engspeed, InPtr);HMI_Text_DisPtr->CMD_End = HMI_CMD_END;HMI_Text_Dis_Que.Rear =(uint8_t)(HMI_Text_Dis_Que.Rear+1)%HMI_TEXTDIS_QUELEN;}if(HMI_Text_Dis_Que.Front !=(HMI_Text_Dis_Que.Rear+1)%HMI_TEXTDIS_QUELEN) {HMI_Text_DisPtr = HMI_Text_Dis_Que.HMI_Text_Dis + HMI_Text_Dis_Que.Rear;HMI_Text_DisPtr->Cmd_Start = HMI_CMD_START;HMI_Text_DisPtr->Cmd_Type = HMI_CMD_TEXTDIS_ASCII;HMI_Text_DisPtr->Start_Point.x = 590;HMI_Text_DisPtr->Start_Point.y = 150;if(actualengtorque<12500){actualengtorque = 12500 - actualengtorque;Digit2AsciiPos0(actualengtorque, HMI_Text_Dis_Que.Rear);}else{actualengtorque = actualengtorque - 12500;Digit2Ascii0(actualengtorque, HMI_Text_Dis_Que.Rear);}HMI_Text_DisPtr->Cmd_End = HMI_CMD_END;HMI_Text_Dis_Que.Rear =(uint8_t)(HMI_Text_Dis_Que.Rear+1)%HMI_TEXTDIS_QUELEN; //进列一项}Record_Write();}///----------------------------------------------------------------------------------------------------------//Function://Param://Return://note///----------------------------------------------------------------------------------------------------------void EEC2_Process(uint8_t OutPtr, uint8_t InPtr){uint32_t accpedalpos1;eec2 = (EEC2_t *)CAN_RxQue.PDUs[OutPtr].Bits.DataField;accpedalpos1 = ((uint32_t)(eec2->accpedalPos1)) * 40;if(HMI_Text_Dis_Que.Front !=(HMI_Text_Dis_Que.Rear+1)%HMI_TextDIS_QUELEN) //目的队列未满,可入列{HMI_Text_DisPtr = HMI_Text_Dis_Que.HMI_Text_Dis +HMI_Text_Dis_Que.Rear; //指向入列项HMI_Text_DisPtr->CMD_Start = HMI_CMD_START; //写入命令头HMI_Text_DisPtr->CMD_Type = HMI_CMD_TEXTDIS_ASCII; //写入命令种类HMI_Text_DisPtr->Start_Point.x = 145; //文本显示位置x坐标HMI_Text_DisPtr->Start_Point.y = 315; //文本显示位置y坐标Digit2Ascii0(accpedalpos1, InPtr); //%HMI_Text_DisPtr->CMD_End = HMI_CMD_END;HMI_Text_Dis_Que.Rear =(uint8_t)(HMI_Text_Dis_Que.Rear+1)%HMI_TEXTDIS_QUELEN; //进列一项}Record_Write();}///----------------------------------------------------------------------------------------------------------//Function://Param://Return://note///----------------------------------------------------------------------------------------------------------void EEC3_Process(uint8_t OutPtr, uint8_t InPtr){eec3 = (EEC3_t *)CAN_RxQue.PDUs[OutPtr].Bits.DataField;Record_Write();}///----------------------------------------------------------------------------------------------------------//Function://Param://Return://note///----------------------------------------------------------------------------------------------------------void ET1_Process(uint8_t OutPtr, uint8_t InPtr){uint32_t engcoolanttemp;et1 = (ET1_t *)CAN_RxQue.PDUs[OutPtr].Bits.DataField;engcoolanttemp = ((uint32_t)(et1->EngCoolantTemp)) *100;if(HMI_Text_Dis_Que.Front !=(HMI_Text_Dis_Que.Rear+1)%HMI_TextDIS_QUELEN) //目的队列未满,可入列{HMI_Text_DisPtr = HMI_Text_Dis_Que.HMI_Text_Dis +HMI_Text_Dis_Que.Rear; //指向入列项HMI_Text_DisPtr->CMD_Start = HMI_CMD_START; //写入命令头HMI_Text_DisPtr->CMD_Type = HMI_CMD_TEXTDIS_ASCII; //写入命令种类HMI_Text_Dis_Que.HMI_Text_Dis[InPtr].Start_Point.x = 145; //文本显示位置x坐标HMI_Text_Dis_Que.HMI_Text_Dis[InPtr].Start_Point.y = 390;if(engcoolanttemp<4000){engcoolanttemp = 4000 - engcoolanttemp;Digit2AsciiPos0(engcoolanttemp, InPtr);}else{engcoolanttemp = engcoolanttemp - 4000;Digit2Ascii0(engcoolanttemp, InPtr);}HMI_Text_DisPtr->CMD_End = HMI_CMD_END;HMI_Text_Dis_Que.Rear =(uint8_t)(HMI_Text_Dis_Que.Rear+1)%HMI_TEXTDIS_QUELEN; //进列一项}Record_Write();}///----------------------------------------------------------------------------------------------------------//Function://Param://Return://note///----------------------------------------------------------------------------------------------------------void CCVS_Process(uint8_t OutPtr, uint8_t InPtr){uint32_t vehiclespeed;ccvs = (CCVS_t *)CAN_RxQue.PDUs[OutPtr].Bits.DataField;vehiclespeed = (((uint32_t)swab16(ccvs->VehicleSpeed)) * 100) >> 8;if(HMI_Text_Dis_Que.Front !=(HMI_Text_Dis_Que.Rear+1)%HMI_TEXTDIS_QUELEN) //目的队列未满,可入列{HMI_Text_DisPtr = HMI_Text_Dis_Que.HMI_Text_Dis +HMI_Text_Dis_Que.Rear; //指向入列项HMI_Text_DisPtr->CMD_Start = HMI_CMD_START; //写入命令头HMI_Text_DisPtr->CMD_Type = HMI_CMD_TEXTDIS_ASCII; //写入命令种类HMI_Text_DisPtr->Start_Point.x = 370; //文本显示位置x坐标HMI_Text_DisPtr->Start_Point.y = 150; //文本显示位置y坐标Digit2Ascii1(vehiclespeed, InPtr); //%HMI_Text_DisPtr->CMD_End = HMI_CMD_END;HMI_Text_Dis_Que.Rear =(uint8_t)(HMI_Text_Dis_Que.Rear+1)%HMI_TEXTDIS_QUELEN; //进列一项}Record_Write();}///----------------------------------------------------------------------------------------------------------//Function://Param://Return://note///----------------------------------------------------------------------------------------------------------void LFE_Process(uint8_t OutPtr, uint8_t InPtr){uint32_t engfuelrate;lfe = (LFE_t *)CAN_RxQue.PDUs[OutPtr].Bits.DataField;engfuelrate = ((uint32_t)swab16(lfe->EngFuelRate)) * 5;if(HMI_Text_Dis_Que.Front !=(HMI_Text_Dis_Que.Rear+1)%HMI_TEXTDIS_QUELEN) {HMI_Text_DisPtr = HMI_Text_Dis_Que.HMI_Text_Dis +HMI_Text_Dis_Que.Rear;HMI_Text_DisPtr->Cmd_Start = HMI_CMD_START;HMI_Text_DisPtr->Cmd_Type = HMI_CMD_TEXTDIS_ASCII;HMI_Text_DisPtr->Start_Point.x = 370;HMI_Text_DisPtr->Start_Point.y = 365;Digit2Ascii0(engfuelrate, InPtr);HMI_Text_DisPtr->Cmd_End = HMI_CMD_END;HMI_Text_Dis_Que.Rear =(uint8_t)(HMI_Text_Dis_Que.Rear+1)%HMI_TEXTDIS_QUELEN; //进列一项}Record_Write();}///----------------------------------------------------------------------------------------------------------//Function://Param://Return://note///----------------------------------------------------------------------------------------------------------static void AMB_Process(uint8_t OutPtr, uint8_t InPtr){amb = (AMB_t *)CAN_RxQue.PDUs[OutPtr].Bits.DataField;Record_Write();}///----------------------------------------------------------------------------------------------------------//Function://Param://Return://note///----------------------------------------------------------------------------------------------------------void IC1_Process(uint8_t OutPtr, uint8_t InPtr){uint32_t engintakemanifold1temp; // 进气温度uint32_t engairinletpressure; //绝对增压压力ic1 = (IC1_t *)CAN_RxQue.PDUs[OutPtr].Bits.DataField;engintakemanifold1temp = ((uint32_t)(ic1->EngIntakeManifold1Temp)) * 100;engairinletpressure = ((uint32_t)(ic1->EngAirInletPressure)) * 200;if(HMI_Text_Dis_Que.Front !=(HMI_Text_Dis_Que.Rear+1)%HMI_TextDIS_QUELEN) //目的队列未满,可入列{HMI_Text_DisPtr = HMI_Text_Dis_Que.HMI_Text_Dis +HMI_Text_Dis_Que.Rear; //指向入列项HMI_Text_DisPtr->CMD_Start = HMI_CMD_START; //写入命令头HMI_Text_DisPtr->CMD_Type = HMI_CMD_TEXTDIS_ASCII; //写入命令种类HMI_Text_DisPtr->Start_Point.x = 370; //文本显示位置x坐标HMI_Text_DisPtr->Start_Point.y = 255;if(engintakemanifold1temp<4000){engintakemanifold1temp = 4000 - engintakemanifold1temp;Digit2AsciiPos0(engintakemanifold1temp, InPtr);}else{engintakemanifold1temp = engintakemanifold1temp - 4000;Digit2Ascii0(engintakemanifold1temp, InPtr);}HMI_Text_DisPtr->CMD_End = HMI_CMD_END;HMI_Text_Dis_Que.Rear =(uint8_t)(HMI_Text_Dis_Que.Rear+1)%HMI_TextDIS_QUELEN; //进列一项}if(HMI_Text_Dis_Que.Front !=(HMI_Text_Dis_Que.Rear+1)%HMI_TEXTDIS_QUELEN) {HMI_Text_DisPtr = HMI_Text_Dis_Que.HMI_Text_Dis +HMI_Text_Dis_Que.Rear;HMI_Text_DisPtr->CMD_Start = HMI_CMD_START;HMI_Text_DisPtr->Cmd_Type = HMI_CMD_TEXTDIS_ASCII;HMI_Text_DisPtr->Start_Point.x = 590;//590HMI_Text_DisPtr->Start_Point.y = 255;Digit2Ascii0(engairinletpressure, HMI_Text_Dis_Que.Rear);HMI_Text_DisPtr->Cmd_End = HMI_CMD_END;HMI_Text_Dis_Que.Rear =(uint8_t)(HMI_Text_Dis_Que.Rear+1)%HMI_TEXTDIS_QUELEN; //进列一项}Record_Write();}///----------------------------------------------------------------------------------------------------------//Function://Param://Return://note///----------------------------------------------------------------------------------------------------------void VEP1_Process(uint8_t OutPtr, uint8_t InPtr){uint32_t batterybotentialswitched;vep1 = (VEP1_t *)CAN_RxQue.PDUs[OutPtr].Bits.DataField;batterybotentialswitched = ((uint32_t)swab16(vep1->BatteryPotentialSwitched))*5;if(HMI_Text_Dis_Que.Front !=(HMI_Text_Dis_Que.Rear+1)%HMI_TEXTDIS_QUELEN) {HMI_Text_DisPtr = HMI_Text_Dis_Que.HMI_Text_Dis +HMI_Text_Dis_Que.Rear;HMI_Text_DisPtr->Cmd_Start = HMI_CMD_START;HMI_Text_DisPtr->Cmd_Type = HMI_CMD_TEXTDIS_ASCII;HMI_Text_DisPtr->Start_Point.x = 590;HMI_Text_DisPtr->Start_Point.y = 365;Digit2Ascii1(batterybotentialswitched, InPtr);HMI_Text_DisPtr->Cmd_End = HMI_CMD_END;HMI_Text_Dis_Que.Rear =(uint8_t)(HMI_Text_Dis_Que.Rear+1)%HMI_TextDIS_QUELEN;}Record_Write();}///----------------------------------------------------------------------------------------------------------//Function://Param://Return://note///----------------------------------------------------------------------------------------------------------void EFL_P1_Process(uint8_t OutPtr, uint8_t InPtr){uint32_t engoilpressure;efl_p1 = (EFL_P1_t *)CAN_RxQue.PDUs[OutPtr].Bits.DataField;engoilpressure = ((uint32_t)(efl_p1->EngOilPressure)) * 400;if(HMI_Text_Dis_Que.Front !=(HMI_Text_Dis_Que.Rear+1)%HMI_TEXTDIS_QUELEN) //目的队列未满,可入列{HMI_Text_DisPtr = HMI_Text_Dis_Que.HMI_Text_Dis +HMI_Text_Dis_Que.Rear; //指向入列项HMI_Text_DisPtr->CMD_Start = HMI_CMD_START; //写入命令头HMI_Text_DisPtr->CMD_Type = HMI_CMD_TEXTDIS_ASCII; //写入命令种类HMI_Text_DisPtr->Start_Point.x = 145; //文本显示位置x坐标HMI_Text_DisPtr->Start_Point.y = 230; //文本显示位置y坐标Digit2Ascii0(engoilpressure, InPtr);HMI_Text_DisPtr->Cmd_End = HMI_CMD_END;HMI_Text_Dis_Que.Rear =(uint8_t)(HMI_Text_Dis_Que.Rear+1)%HMI_TEXTDIS_QUELEN; //进列一项}Record_Write();}///----------------------------------------------------------------------------------------------------------//Function://Param://Return://note///----------------------------------------------------------------------------------------------------------void LFC_Process(uint8_t OutPtr, uint8_t InPtr){uint32_t engtotalfuelused;lfc = (LFC_t *)CAN_RxQue.PDUs[OutPtr].Bits.DataField;engtotalfuelused = ((uint32_t)swab32(lfc->EngTotalFuelUsed))>>1 ;if(HMI_Text_Dis_Que.Front !=(HMI_Text_Dis_Que.Rear+1)%HMI_TextDIS_QUELEN) //目的队列未满,可入列{HMI_Text_DisPtr = HMI_Text_Dis_Que.HMI_Text_Dis +HMI_Text_Dis_Que.Rear; //指向入列项HMI_Text_DisPtr->CMD_Start = HMI_CMD_START; //写入命令头HMI_Text_DisPtr->CMD_Type = HMI_CMD_TEXTDIS_ASCII; //写入命令种类HMI_Text_DisPtr->Start_Point.x = 125; //文本显示位置x坐标HMI_Text_DisPtr->Start_Point.y = 220; //文本显示位置y坐标Digit2Ascii1(engtotalfuelused, InPtr);HMI_Text_DisPtr->Cmd_End = HMI_CMD_END;HMI_Text_Dis_Que.Rear =(uint8_t)(HMI_Text_Dis_Que.Rear+1)%HMI_TEXTDIS_QUELEN; //进列一项}Record_Write();}///----------------------------------------------------------------------------------------------------------//Function://Param://Return://note///----------------------------------------------------------------------------------------------------------CAN_EXT void FAULT_MEMORY_Process(uint8_t OutPtr, uint8_t InPtr, uint8_t Touch_flag, uint16_t num){uint16_t Fault_Type;uint8_t error1[]="安全晶体管电磁阀阵列1(高边)故障"; uint8_t error2[]="安全晶体管电磁阀阵列1(低边)故障"; uint8_t error3[]="安全晶体管电磁阀阵列3(高边)故障"; uint8_t error4[]="存储器控制错误";uint8_t error5[]="看门狗控制错误";uint8_t error6[]="处理器控制错误";uint8_t error7[]="TRAP控制错误";uint8_t error8[]="5V电压控制错误";uint8_t error9[]="12V传感器电压控制错误";uint8_t error10[]="12.5V电压控制错误";uint8_t error11[]="24V电压错误";uint8_t error12[]="nvSRAM控制错误";uint8_t error13[]="nvSRAM数据控制错误";uint8_t error14[]="CAN接口初始化错误";uint8_t error15[]="SEAJ1939协议错误";uint8_t error16[]="传感器电缆堵塞";uint8_t error17[]="温度传感器。
单片机原理及应用-S12X单片机的结构与组成

单片机原理及应用-S12X单片机的结构与组成单片机原理及应用S12X 单片机的结构与组成在当今的电子技术领域,单片机的应用可谓无处不在。
从智能家居到工业控制,从汽车电子到医疗设备,单片机都扮演着至关重要的角色。
其中,S12X 单片机以其出色的性能和独特的结构组成,在众多单片机中脱颖而出。
S12X 单片机是飞思卡尔(现恩智浦)推出的一款高性能 16 位单片机。
它采用了增强型的 HCS12 内核,相较于传统的 8 位单片机,具有更强的处理能力和更丰富的功能。
从硬件结构上看,S12X 单片机主要由以下几个部分组成:1、中央处理器(CPU):这是单片机的核心,负责执行指令和进行数据处理。
S12X 的 CPU 采用了 16 位的架构,具有较高的运算速度和处理能力。
2、存储器:包括程序存储器(Flash 或 ROM)和数据存储器(RAM)。
程序存储器用于存储用户编写的程序代码,而数据存储器则用于存储运行过程中的临时数据。
S12X 单片机通常具有较大的存储空间,以满足复杂应用的需求。
3、输入/输出(I/O)端口:用于与外部设备进行数据交换。
这些端口可以配置为不同的工作模式,如输入、输出、高阻态等,以适应各种接口需求。
4、定时器/计数器:用于实现定时、计数和脉冲宽度调制(PWM)等功能。
S12X 单片机通常配备多个定时器/计数器,以满足不同的定时和计数需求。
5、串行通信接口:如SCI(串行通信接口)、SPI(串行外设接口)和 IIC(集成电路间总线)等,用于与其他设备进行串行数据通信。
6、模数转换器(ADC):用于将模拟信号转换为数字信号,以便单片机进行处理。
7、脉宽调制模块(PWM):可以生成不同占空比的脉冲信号,用于控制电机、灯光等设备。
在软件方面,S12X 单片机通常使用特定的开发工具和编程语言进行编程。
常见的编程语言有 C 语言和汇编语言。
开发人员可以使用这些语言编写程序,并通过下载工具将程序烧录到单片机的存储器中。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Page 2
第七章 用C语言开发应用程序 语言开发应用程序 —编辑、编译、链接、定位 编辑、编译、链接、
集成开发环境IDE:将应用程序的编辑、编译、链接、定位、调试等集成在 :将应用程序的编辑、编译、链接、定位、 集成开发环境 一个大的软件包中,简化开发工作。但用户往往不清楚操作的原理。 一个大的软件包中,简化开发工作。但用户往往不清楚操作的原理。
flag=0; CLR 0X2100
0x2000~0x20FF为栈空间(STACKSIZE 0x100 ) 0x2100为定义的第一个全局变量flag的地址(见*.map文件) 虽然使用全局变量传递参数非常方便,但在多任务环境下,多个任务访问某个 全局变量会引起竞争(如中断服务程序和主程序都访问同一个全局变量)。
2、避免使用浮点数和双精度 、 3、C语言数据类型的位宽取决于单片机的类型和具体的 语言数据类型的位宽取决于单片机的类型和具体的IDE中的约定; 中的约定; 、 语言数据类型的位宽取决于单片机的类型和具体的 中的约定 中工程窗口中的“ 标签下“ 如codewarrior中工程窗口中的“target”标签下“standard”对话框中 中工程窗口中的 标签下 对话框中 “complier for”中 “Type sizes”按钮对应的对话框 中 按钮对应的对话框 Page 6
微控制器的编程是围绕存储器的
代码保存在存储器中 变量使用存储器 外设的控制实际是通过对存储器的访问来实现
Page 5
第七章 用C语言开发应用程序 语言开发应用程序 —编辑、编译、链接、定位 编辑、编译、链接、
7.2 开发嵌入式应用的 编译器的特点 开发嵌入式应用的C编译器的特点
注意变量的数据类型ቤተ መጻሕፍቲ ባይዱ
1、RAM空间有限,选择适合变量取值范围的数据类型,尤其是数组;适合的数 、 空间有限,选择适合变量取值范围的数据类型,尤其是数组; 空间有限 据类型能节省代码长度,缩短执行周期; 据类型能节省代码长度,缩短执行周期; Signed/unsigned char/int/short/long 每个数据类型都用特定的范围如下: 每个数据类型都用特定的范围如下:
第七章 用C语言开发应用程序 语言开发应用程序 —编辑、编译、链接、定位 编辑、编译、链接、
4、尽量不调整编译器默认的数 尽量不调整编译器默认的数 据类型的位宽,避免使用 据类型的位宽, 原始的数据类型, 原始的数据类型,而是通 过声明统一化的间接数据 类型。 类型。
#typedef unsigned char u8_t #typedef int u16_t #typedef unsigned long u32_t u16_t a; function() { a=5; a+=3; }
第七章 用C语言开发应用程序 语言开发应用程序 ———函数 函数
7.4 函数的结构与函数间参数的传递
函数间传递参数通常有两种方法:使用全局变量和形参。 1、全局变量
全局变量从RAM低地址堆起。但由于CodeWarrior默认在RAM低地址保留栈空 间,将堆栈视为第1个全局变量,所以全局变量紧随堆栈之后。例如: #include <hidef.h> /* common defines and macros */ #include "derivative.h" /* derivative-specific definitions */ extern void delay1(unsigned int countert); unsigned char flag; ……
Page 1
第七章 用C语言开发应用程序 语言开发应用程序 —编辑、编译、链接、定位 编辑、编译、链接、
7.1 C语言是开发单片机应用软件的有力工具 语言是开发单片机应用软件的有力工具
标准ANSI C:通用计算机上有操作系统的 语言 标准 :通用计算机上有操作系统的C语言 嵌入式C: 编译器需特殊处理与 编译器需特殊处理与CPU硬件相关的内容,随着单片机系统 硬件相关的内容, 嵌入式 :C编译器需特殊处理与 硬件相关的内容 程序空间的增大(可达4M), 语言的应用越来越广泛( ),C语言的应用越来越广泛 程序空间的增大(可达 ), 语言的应用越来越广泛(>4K)。 )。 µC/OS-II:实时操作系统RTOS,是指当外界事件或数据产生时,能 / - :实时操作系统 ,是指当外界事件或数据产生时, 够接受并以足够快的速度予以处理, 够接受并以足够快的速度予以处理,其处理的结果又能在规定的时间之 内来控制生产过程或对处理系统作出快速响应, 内来控制生产过程或对处理系统作出快速响应,并控制所有实时任务协 调一致运行的操作系统。保证系统的实时性、可靠性和稳定性。 调一致运行的操作系统。保证系统的实时性、可靠性和稳定性。 嵌入式C的优势:移植性好、库函数丰富、可读性好、便于使用 嵌入式 的优势:移植性好、库函数丰富、可读性好、便于使用RTOS。 的优势 。 汇编语言的优势:编写系统的硬件相关部分更直观、方便,代码少、 汇编语言的优势:编写系统的硬件相关部分更直观、方便,代码少、执 行速度快。常用于: 行速度快。常用于: • • • 系统的初始化 中断向量的初始化, 中断向量的初始化,开、关中断 I/O口的输入输出函数 口的输入输出函数
交叉编译:是指在一台大一些、 交叉编译:是指在一台大一些、
生目标系统的机器码。 生目标系统的机器码。目标系统 计算机的CPU类型完全不同。 类型完全不同。 计算机的 类型完全不同
第七章 用C语言开发应用程序 语言开发应用程序 —编辑、编译、链接、定位 编辑、编译、链接、
*.h *.c *.c++ C源文件 源文件 汇编源文件
Page 8
第七章 用C语言开发应用程序 语言开发应用程序 ———运行环境 运行环境
7.3 建立 语言程序运行环境 建立C语言程序运行环境
C语言的主程序从main()开始的,必须为main() 建立一个程序运行环境, 主要完成四件事情: 1、设置栈指针初值 2、相关硬件的系统初始化 3、调用函数main() 使之执行 4、给出main() 完成后的出口,即执行exit()。
最简情况下,只需1、3。 CodeWarrior默认在RAM低地址保留栈空间。 硬件的初始化通常包括相关寄存器初始化、时钟初始化、串行口初始化等 实际应用中,应用程序往往是一个死循环,不用4。调试时,可以把监控程序 的热启动地址作为出口
Page 9
第七章 用C语言开发应用程序 语言开发应用程序 ———运行环境 运行环境
Page 7
第七章 用C语言开发应用程序 语言开发应用程序 —编辑、编译、链接、定位 编辑、编译、链接、
7.2 开发嵌入式应用的 编译器的特点 开发嵌入式应用的C编译器的特点
注意函数的可重入性 在多任务环境下,允许某个函数同时被一个以上的任务调用,称该函数 具备可重入性。如果知道某个库函数中使用了全局变量,就可以认为这 个函数是不可重入的。
Page 11
第七章 用C语言开发应用程序 语言开发应用程序 ———函数 函数
7.4 函数的结构与函数间参数的传递
2、局部变量
局部变量是某个函数的“私有”变量,是在栈空间定义的,局部变量实际上 是子程序要用到的一块内存空间。例如: void main(void) { unsigned char i,settime; unsigned int j,m,n; …… } 局部变量只在函数内部有意义,它所占用的一块栈空间在子程序返回前会释 放掉,因此局部变量不涉及到参数传递。 (SP=0x2100)__ (SP=0x20F8)__
CodeWarrior自动生成Start12.c文件建立运行环境 创建新工程过程中,当选择了C编程语言后,有以下选择: 1、选择最小化的 startup代码
2、选择小模式:适用 于整个应用程序都 在64KB寻址空间 内的情况,若需分 页,自行处理。 3、Debug调试时,复 位后单步执行,可 以看到运行环境的 建立过程。 10 Page
*.asm *.inc
链接配 置文件
*.prm
C编译器 汇编编译器
列表文件
目标文件
*.obj
库文件
*.lst 反 编 译 器
链接器 *.sx 执行文件 *.abs
汇编 反编译文件
映射文件
*.map
Page 4
第七章 用C语言开发应用程序 语言开发应用程序 —编辑、编译、链接、定位 编辑、编译、链接、
Page 12
第七章 用C语言开发应用程序 语言开发应用程序 ———函数 函数
7.4 函数的结构与函数间参数的传递
3、形式参数
函数的形式参数也被安排在栈空间,参数传递是通过调用函数将值复制给被调 用的形式参数实现的,即参数是通过堆栈传递的。 使用的C编译器不同,参数进入堆栈的顺序以及最后一个参数或第一个参数保 存在什么地方也会有所不同。 CodeWarrior的传递规则: (1) 返回参数:return(n)中的n值。char n,则在B寄存器;int n,则在D寄存器; 其它类型,则返回一个指向n的指针,存在D寄存器。 (2) 定义函数:多个形参时,从右往左,第一个参数读D寄存器,其它依次读取 以堆栈指针为基地址,加上2(绕过函数程序的返回地址)开始 的堆栈空间内,左边第一个参数偏移量的值最大。
第七章 用C语言开发应用程序 语言开发应用程序
• • • • • 7.1 C语言是开发单片机应用软件的有力工具 语言是开发单片机应用软件的有力工具 7.2 开发嵌入式应用的 编译器的特点 开发嵌入式应用的C编译器的特点 7.3 建立 语言程序运行环境 建立C语言程序运行环境 7.4 函数的结构与函数间参数的传递 7.5 应用程序的模块化及其框架
1. 编辑程序源代码: *.c, *.asm, *.h ; 编辑程序源代码: 2. 预编译:对源代码文件中的文件包含(include)、预编译语句(#define)等进行分析、 预编译:对源代码文件中的文件包含( 、预编译语句( )等进行分析、 检查声明、定义的完整性,转换成C编译器可接受的格式 编译器可接受的格式; 检查声明、定义的完整性,转换成 编译器可接受的格式; 3. 编译 :检查和报告相关的语法错误,然后将 程序转换成汇编器可接受的代码。 检查和报告相关的语法错误,然后将C程序转换成汇编器可接受的代码 程序转换成汇编器可接受的代码。 4. 汇编 :生成针对某种 生成针对某种CPU的汇编浮动代码文件,*.obj; 的汇编浮动代码文件, 的汇编浮动代码文件 ; 5. 链接 :将浮动的 将浮动的*.obj文件模块按指定顺序链接起来,并且将所用到的 语言标准库函 文件模块按指定顺序链接起来, 文件模块按指定顺序链接起来 并且将所用到的C语言标准库函 用起来更方便的计算机上编译产 数也从各自所在的函数库中调出,把 文件中缺失的那些参数补上, 数也从各自所在的函数库中调出 把*.obj文件中缺失的那些参数补上,*.prm; 文件中缺失的那些参数补上 ; 6. 定位 :根据目标系统硬件的情况,给程序分配程序空间的地址、数据空间的地址以及 根据目标系统硬件的情况,给程序分配程序空间的地址、 所用的CPU及指令系统与所用的 所用的 及指令系统与所用的 程序运行的其实地址等,生成可执行的目标代码, 程序运行的其实地址等,生成可执行的目标代码,*.abs,*.sx; ; 7. 下载 :将*.sx文件下载到单片机的程序空间的相应地址内; 文件下载到单片机的程序空间的相应地址内; 文件下载到单片机的程序空间的相应地址内 8. 调试、运行 调试、 9. 反汇编:将目标代码反汇编成汇编语言,以便用户对应用程序中特别关键的部分进一 反汇编:将目标代码反汇编成汇编语言, 步优化( 步优化(project->Disassemble)。 。 Page 3