⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 实验7 在RAM中执行程序代码 实验7 在RAM中执行程序代码 实验7 在RAM中执行程序代码
💻 C
字号:
/*******************************************************************************
程序名称:引导程序,通过串行口加载HEX程序文件到片外RAM并运行
硬件接法:P1.2控制交流蜂鸣器发声
          片外接16KB RAM,地址范围0x8000~0xBFFF
功能描述:通过串行口加载HEX程序文件,转换成BIN格式并保存在片外RAM中;
          加载完毕后蜂鸣器鸣叫,并等待按下K4;
          K4按下后,跳转到RAM去执行程序。
*******************************************************************************/


#include <REG52.h>
#include <ABSACC.H>
#include <ctype.h>
#include <string.h>
#include <stdio.h>


//定义I/O端口
sbit BUZZER = P1^2;	//交流蜂鸣器
sbit K4 = P3^5;		//按键,按下时输入低电平


//设置晶振频率
#define MCLK		11059200L
//设置波特率
#define BaudRate	4800L


//外部中断INT0入口
void INT0_ISR() interrupt 0
{
#pragma asm
	LJMP	0x8003
#pragma endasm
}

//定时器T0中断入口
void T0_ISR() interrupt 1
{
#pragma asm
	LJMP	0x800B
#pragma endasm
}

//外部中断INT1入口
void INT1_ISR() interrupt 2
{
#pragma asm
	LJMP	0x8013
#pragma endasm
}

//定时器T1中断入口
void T1_ISR() interrupt 3
{
#pragma asm
	LJMP	0x801B
#pragma endasm
}

//串行口收发中断入口
void Serial_ISR() interrupt 4
{
#pragma asm
	LJMP	0x8023
#pragma endasm
}

//定时器T2中断入口
void T2_ISR() interrupt 5
{
#pragma asm
	LJMP	0x802B
#pragma endasm
}


//串行口初始化
void UartInit()
{
//串行口设置:8位UART,允许接收,TI置位
	SCON = 0x52;
//波特率加倍
	PCON |= 0x80;
//设置定时器T1为8位自动重装模式
	TMOD &= 0x0F;
	TMOD |= 0x20;
//设置定时器T1的初值
	TH1 = 256 - ( MCLK / 12 ) / (16 * BaudRate );
	TL1 = TH1;
//启动定时器T1
	TR1 = 1;
}


//定义联合整型结构,为访问整型变量的字节部分提供了方便
typedef union
{
	unsigned int i;
	struct
	{
		unsigned char H;
		unsigned char L;
	}CharPart;
}UnionInt;


//定义Intel HEX记录的结构
typedef struct
{
	unsigned char ll;	//长度
	unsigned int aaaa;	//地址
	unsigned char tt;	//记录类型,0-数据,1-终止
	char dd[32];		//数据
	char cc;			//校验和
	unsigned int BootAddr;	//启动地址
}CIntelHEX;


/*******************************************************************************
函数:AnalyseHEX()
功能:分析一条HEX记录(把Intel HEX记录的文本转换成IntelHEX结构)
参数:hex[]是记录的文本一行内容
      转换后的结果保存在IntelHEX结构中
返回:1-转换成功
      0-HEX记录文本中有错误
*******************************************************************************/
bit AnalyseHEX(CIntelHEX idata *IntelHEX, char pdata *hex)
{
	unsigned char i;
	unsigned char j;
	unsigned char t;
	unsigned char n;
	unsigned char cc;
	UnionInt x;
//检查冒号
	if ( hex[0] != ':' ) return 0;
//检查长度
	t = (toint(hex[1])<<4) + toint(hex[2]);
	if ( t > 32 ) return 0;
	n = 2 * t + 11;
	if ( n != strlen(hex) ) return 0;
	IntelHEX->ll = t;
	cc = t;
//提取地址
	t = (toint(hex[3])<<4) + toint(hex[4]);
	cc += t;
	x.CharPart.H = t;
	t = (toint(hex[5])<<4) + toint(hex[6]);
	cc += t;
	x.CharPart.L = t;
	IntelHEX->aaaa = x.i;
//提取记录类型
	t = (toint(hex[7])<<4) + toint(hex[8]);
	if ( (t==0) || (t==1) )
	{
		cc += t;
		IntelHEX->tt = t;
	}
	else
	{
		return 0;
	}
//提取数据
	i = 9;
	if ( t == 0 )
	{
		j = 0;
		n = IntelHEX->ll;
		do
		{
			t = (toint(hex[i++])<<4);
			t += toint(hex[i++]);
			cc += t;
			IntelHEX->dd[j++] = t;
		} while ( --n != 0 );
	}
//提取校验和
	t = (toint(hex[i++])<<4);
	t += toint(hex[i++]);
	cc += t;
	IntelHEX->cc = t;
//检查校验和
	if ( cc == 0 )
		return 1;
	else
		return 0;
}


//蜂鸣器鸣叫
void Beep()
{
	unsigned int n;
	TMOD &= 0xF0;	//T0设置在方式1,即16位定时器(不改变T1的模式)
	TMOD |= 0x01;
	n = 800;
	do
	{
		TH0 = 0xFC;			//设置T0初值=65536-(11059200/12)/(2*f)
		TL0 = 0x66;			//f为发声频率(500Hz)
		TR0 = 1;			//启动定时器
		while ( !TF0 );		//等待定时器溢出
		TR0 = 0;			//停止定时器
		TF0 = 0;			//清除溢出标志
		BUZZER = !BUZZER;	//翻转I/O口,产生方波振荡,使蜂鸣器发声
	} while ( --n != 0 );
	BUZZER = 1;
}


/*******************************************************************************
函数:Delay()
功能:延时0.01s~2.56s
参数:t>0时,延时(t*0.01)s
      t=0时,延时2.56s
说明:定时10ms的定时器初值=65536-0.01/(1/(f/12)),其中f为晶振频率
*******************************************************************************/
void Delay(unsigned char t)
{
	TMOD &= 0xF0;	//T0设置在方式1,即16位定时器(不改变T1的模式)
	TMOD |= 0x01;
	do
	{
		TH0 = 0xDC;			//设置定时器初值(定时10ms)
		TL0 = 0x00;
		TR0 = 1;			//启动定时器
		while ( !TF0 );		//等待定时器溢出
		TR0 = 0;			//停止定时器
		TF0 = 0;			//清除溢出标志
	} while ( --t != 0 );	//循环t次
}


//跳到RAM执行程序
void GotoRam()
{
//下载完毕后,发送OK、蜂鸣器鸣叫
	printf("OK, press K4 to executing.\r\n");
	Beep();
//等待按键K4按下,当K4抬起时,才运行RAM程序
	while ( K4 );
	Delay(40);
	while ( !K4 );
//复位重要SFR寄存器
	IE = 0x00;
	TCON = 0x00;
	TMOD = 0x00;
	IP = 0x00;
	SCON = 0x00;
//恢复堆栈指针SP默认值;跳到RAM地址0x8000处
#pragma asm
	MOV		SP, #0x07
	LJMP	0x8000
#pragma endasm
}


/*******************************************************************************
函数:GetString()
功能:从串行口读入一行HEX记录
参数:*s-字符缓冲区,保存读入的数据
      size-最大限制长度
*******************************************************************************/
void GetString(char pdata *s, unsigned char size)
{
	char c;
	unsigned char n;
	n = 0;
	for (;;)
	{
		c = _getkey();
		if ( (c==':') || isxdigit(c) )
		{
			if ( n < size )
			{
				s[n++] = c;
			}
		}
		else if ( c == '\n' )
		{
			s[n] = '\0';
			return;
		}
	}
}


//主程序
void main()
{
	unsigned char n;
	unsigned char i;
	unsigned int addr;
	CIntelHEX idata IntelHEX;
	char pdata buf[76];
	UartInit();
	printf("Ready\r\n");
	for (;;)
	{
		GetString(buf,sizeof(buf)-1);	//从串行口读入一行HEX记录
		if ( AnalyseHEX(&IntelHEX,buf) )	//分析HEX记录,转换成BIN格式
		{
			switch ( IntelHEX.tt )
			{
			case 0x00:	//HEX类型:数据
			//保存BIN代码到RAM
				addr = IntelHEX.aaaa;
				n = IntelHEX.ll;
				for ( i=0; i<n; i++ )
				{
					XBYTE[addr+i] = IntelHEX.dd[i];
				}
				break;
			case 0x01:	//HEX类型:结束
			//跳到RAM中运行程序代码
				GotoRam();
				break;
			default:
				break;
			}
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -