从单片机基础到程序框架(全集 2019pdf版).pdf - 第779页
第一百三十一节: 灵活切换各种不同大小“接收内存”的 串口程序框架。 【131.1 切换各种不同大小“接收内存” 。 】 很多 32 位的 单片机, 只要 外挂 S RAM 或者 SDRA M 这类内存芯片, 就可以轻松 的把一个全局 变量的数组开 辟到几百 K 甚至几兆的 容量 。 开辟 这么大 的数组, 往往是用来处理一些文 件类的大数据 , 比如串口接收一 张 480x272 点阵大小的 .BMP 格式 的图片文件 , 就需要开辟…

for(;u32DelayTime>0;u32DelayTime--);
}
void PeripheralInitial(void)
{
}
void BeepOpen(void)
{
P3_4=0;
}
void BeepClose(void)
{
P3_4=1;
}
void VoiceScan(void)
{
static unsigned char Su8Lock=0;
if(1==vGu8BeepTimerFlag&&vGu16BeepTimerCnt>0)
{
if(0==Su8Lock)
{
Su8Lock=1;
BeepOpen();
}
else
{
vGu16BeepTimerCnt--;
if(0==vGu16BeepTimerCnt)
{
Su8Lock=0;
BeepClose();
}
}
}
}

第一百三十一节: 灵活切换各种不同大小“接收内存”的串口程序框架。
【131.1 切换各种不同大小“接收内存”。】
很多 32 位的单片机,只要外挂 SRAM 或者 SDRAM 这类内存芯片,就可以轻松的把一个全局变量的数组开
辟到几百 K 甚至几兆的容量。开辟这么大的数组,往往是用来处理一些文件类的大数据,比如串口接收一张
480x272 点阵大小的.BMP 格式的图片文件,就需要开辟一个几百 K 的全局变量大数组。串口通信中,从接收
内存的容量来划分,常用有两种数据类型,一种是常规控制类(容量小),一种是文件类(容量大),要能做
到在这两种“接收内存”中灵活切换,关键是用到“指针的中转切换”技术。
“常规控制类内存”负责两块事务,一块是接收“前部分的”[数据头,数据类型,数据长度],另一块
是“后部分的”[常规控制类的专用数据]。
“文件类内存”只负责“后部分的”[文件类的专用数据],而“前部分的”[数据头,数据类型,数据
长度]是需要借助“常规控制类内存”来实现的。
本节破题的关键在于,根据不同的数据类型,利用“指针的中转切换”实现不同接收内存的灵活切换。
关键代码是串口中断函数这部分的处理,片段代码的讲解如下:
unsigned char Gu8ReceBuffer[20]; //常规控制类的小内存
unsigned char Gu8FileBuffer[40]; //文件类的大内存
unsigned char *pGu8ReceBuffer; //用来切换接收内存的“中转指针”
unsigned long Gu32ReceCntMax=20; //最大缓存(初始值 20 或者 40 都没关系,因为后续会动态改变)
void usart(void) interrupt 4
{
if(1==RI)
{
RI = 0;
if(0==Gu8FinishFlag)
{
Gu8ReceFeedDog=1;
switch(Gu8ReceStep)
{
case 0: //“前部分的”数据头。接头暗号的步骤
Gu8ReceBuffer[0]=SBUF;
if(0xeb==Gu8ReceBuffer[0])
{
Gu32ReceCnt=1;
Gu8ReceStep=1;
}
break;
case 1: //“前部分的”数据类型和长度
Gu8ReceBuffer[Gu32ReceCnt]=SBUF;

Gu32ReceCnt++;
if(Gu32ReceCnt>=6) //前 6 个数据。接收完了“数据类型”和“数据长度”。
{
Gu8ReceType=Gu8ReceBuffer[1]; //提取“数据类型”
pu32Data=(unsigned long *)&Gu8ReceBuffer[2];
Gu32ReceDataLength=*pu32Data; //提取“数据长度”
if(Gu32ReceCnt>=Gu32ReceDataLength) //靠“数据长度”来判断是否完成
{
Gu8FinishFlag=1; //接收完成标志“置 1”,通知主函数处理。
Gu8ReceStep=0; //及时切换回接头暗号的步骤
}
else //如果还没结束,继续切换到下一个步骤,接收“有效数据”
{
//以下几行代码是本节的破题关键!!!
if(0x02==Gu8ReceType) //如果是文件类,把指针关联到 Gu8FileBuffer
{
pGu8ReceBuffer=(unsigned char *)&Gu8FileBuffer[0];//下标 0
Gu32ReceCntMax=40+6; //最大缓存
}
else //如果是常规类,继续把指针关联到 Gu8ReceBuffer 本身的数组
{
pGu8ReceBuffer=(unsigned char *)&Gu8ReceBuffer[6];//下标 6
Gu32ReceCntMax=20; //最大缓存
}
Gu8ReceStep=2; //切换到下一个步骤
}
}
break;
case 2: //“后部分的”数据
pGu8ReceBuffer[Gu32ReceCnt-6]=SBUF; //这里的指针就是各种不同内存的化身!!!
Gu32ReceCnt++; //每接收一个字节,数组下标都自加 1,为接收下一个数据做准备
//靠“数据长度”来判断是否完成。也不允许超过数组的最大缓存的长度
if(Gu32ReceCnt>=Gu32ReceDataLength||Gu32ReceCnt>=Gu32ReceCntMax)
{
Gu8FinishFlag=1; //接收完成标志“置 1”,通知主函数处理。
Gu8ReceStep=0; //及时切换回接头暗号的步骤
}
break;
}
}
}
else //发送数据引起的中断