《嵌入式技术基础与实践》实验报告Word下载.docx
《《嵌入式技术基础与实践》实验报告Word下载.docx》由会员分享,可在线阅读,更多相关《《嵌入式技术基础与实践》实验报告Word下载.docx(21页珍藏版)》请在冰点文库上搜索。
2.2软件结构图
软件包括MCU端与PC端2部分组成,下面分别介绍2部分软件的结构。
2.2.1MCU端软件结构
图2.2MCU端软件结构图
根据需求分析,对需要测试的功能进行编程,MCU端包含LED小灯、LCD显示、开关量输入、键盘输入、AD转换、PWM、FLASH读写、串口数据发送与接受等模块。
MCU端软件结构图,如图2.2所示。
在脱离PC端控制的情况下LED小灯、LCD显示可以得到验证,如果需要验证键盘输入、AD转换与串口数据发送与接收必须与PC端联机操作。
2.2.2PC端软件结构
图2.3PC端软件结构图
PC端使用C#编程,以串口通讯为核心,使用串口与MCU进行通讯实现,对MCU的控制和对MCU反馈信息进行处理,并反映在用户界面上。
根据MCU提供的功能,编写程序匹配其工作。
PC端程序包括串口数据输入输出、开关状态反馈、小灯控制、AD转换数据显示、时钟、PWM控制、FLASH读写、键盘数据显示模块。
软件结构图如图2.3所示。
第3章MCU方的程序设计
本章节将详细介绍MCU端的各个功能模块,其中包括串口数据输入输出、LCD显示、键盘、AD转换、PWM、时钟计时、FLASH读写。
程序基于C语言编写,使用面向硬件对象模块封装的思想。
面向硬件对象模块的封装是对系统中的每个硬件对象建立相对应的头文件和硬件驱动程序文件。
头文件中主要包含该硬件的接口和相应的寄存器设置参数,硬件驱动程序文件主要是对该硬件的驱动,同时标注出各个功能模块的功能,入口,出口和堆栈深度。
这样做剩下的编程工作就只是面向变量和PC的编程,屏蔽的具体硬件对象的差异性,提高了程序的移植性和复用性。
3.1串行通信数据接收与发送
MCU端使用串口中断,实现对串口数据的接收与发送。
串口是MCU与PC通讯的唯一通道,在串口中断处理子程序中,将处理由PC端发送的控制指令与数据。
标志位确定PC端发送指令的类型,并加以处理,使用MCU内部标志位确定所需要做的工作,在中断结束后使用主程序完成相应操作。
串口中断处理程序:
isrSCIre:
接收中断处理函数----*
功能:
接收1个字节数据,发送接到的数据*
总中断关闭,但是接收标志还是有,则直接识别缓冲区,就取走就行。
*
参数:
无*
返回:
内部调用函数:
SCIreN,SCIsendN*
---*
interruptvoidisrSCIre(void)
{
uint8f,i,flag;
标志是否接受到数据
DisableInterrupt();
禁止总中断
接收32个字节的数据
f=SCIReN(1,1,SerialBuff);
若收到数据,则发送接到的数据
if(f==0)
{
if(SerialBuff[0]>
=130&
&
SerialBuff[0]<
=137)
flag=SerialBuff[0];
}
if(flag==130)
light模块
LightBuff=SCIRe1(1,&
i);
elseif(flag==131)LCD标志
{连续接收可以,代码如下
LCDLen=SCIRe1(1,&
LCD显示字符长度
SCIReN(1,LCDLen,ShowBuff);
LCD显示的内容
elseif(flag==132)时钟标志
接收3个字节的数据
SCIReN(1,3,time);
elseif(flag==133)LED标志
pwm处理模块
pwmDutyPC=SCIRe1(1,&
elseif(flag==135)LED标志
接收4个字节的数据
i=SCIReN(1,4,LEDBuff);
if(i==0)
SCISend1(1,135);
SCISendN(1,4,LEDBuff);
for(i=0;
i<
4;
i++)
LEDBuff[i]+='
0'
;
elseif(flag==137)
AD模块
chanelNum=SCIRe1(1,&
else
SCISendN(1,1,SerialBuff);
EnableInterrupt();
开放总中断
}
3.2时钟控制
MCU端实现精度为1秒的时钟计时功能,可以通过PC端发送指令设定当前时间,每秒通过串口发送时钟数据。
使用MCU内部定时器0实现计时,定时器0同时作为PWM使用,所以内部需要解决冲突问题。
中断服务中尽量减少其工作量,所以只对秒信号进行处理,其他计时工作使用主程序完成。
isrT1OV:
定时器溢出中断处理函数:
isrT1OV:
定时器1溢出中断处理函数------*
以秒为最小单位计时,并清定时器1溢出标志位*
内部调用:
SecAdd1:
以秒为最小单位递增时,分,秒缓冲区的值*
-*
interruptvoidisrT1OV(void)
uint8temp;
SecAdd1(time);
1s到,递增时,分,秒缓冲区的值
SCISend1(1,132);
SCISendN(1,3,time);
temp=AW60_TPM_CSTR
(2);
1.读取定时器1状态和控制寄存器T1SC
AW60_TPM_CSTR
(2)&
=~AW60_TPM_CSTR_TOF;
2.向定时器溢出标志TOF写0
开放总中断
键盘中断处理函数:
isrKeyBoard:
键盘中断处理函数*
识别按键并发送键值,把键值转换成对应的定义值,再从串口发送出去*
调用函数:
(1)扫描法读取键值函数(KBscanN)*
(2)键值转为定义值函数(KBdef)*
(3)串行发送一个字节数据(SCIsend1)*
(4)键盘初试化(KBInit)*
interruptvoidisrKeyBoard(void)
uint8value;
uint16i;
i<
1000;
i++);
关总中断
DisableKBint();
屏蔽键盘中断
value=KBScanN(10);
扫描键值,存于value中
if(value!
=0xFF)
SCISend1(1,134);
SCISend1(1,KBDef(value));
键值转化为定义值并发送
KBInit();
键盘初始化键盘中断
EnableKBint();
开放键盘中断
开总中断
3.3主程序
主程序作用是将系统初始化,并且根据标志处理各工作
工程名:
Light*
程序描述:
MCU综合实验,控制系统各个模块工作*
目的:
FreescaleAW系列MCUC语言综合程序*
说明:
包含串口数据输入输出、LCD显示、键盘、AD转换、PWM、时钟计时、FLASH读写等模块*
---苏州大学飞思卡尔嵌入式系统实验室2012年*
voidmain()
仅在本函数中用
uint8i;
uint8ma;
uint8LCDi=0;
定义初始显示缓存并赋初值
constuint8DisPalyInit[]
="
WaitReceiving..Soochow2010.09"
LCDLen=0;
chanelNum=30;
为30,说明没有收到AD转换的客户端信息
pwmDutyPC=101;
1关总中断
1.1芯片初始化
MCUInit();
2.模块初始化
SCIInit(1,SYSTEM_CLOCK,9600);
(1)串口初始化
Light_Init(Light_Run_PORT,Light_Run,Light_OFF);
(2)灯和蜂鸣器的引脚初始化
(3)按键初始化
TPMinit
(2);
(4)定时器2初始化
LEDinit();
PWM(1,0,0x800,0);
定时器2通道0初始输出占空比为0周期为1s的PWM波
ADCInit();
AD初始化
3.LCD显示初始化
LCDshow((uint8*)DisPalyInit);
4.内存初始化
(1)"
时分秒"
缓存初始化(00:
00:
00)
time[0]=0;
time[1]=0;
time[2]=0;
(2)小灯状态初始化3,表示没有命令发送过来
LightBuff=3;
(3)数码管状态初始化
LEDBuff[0]='
8'
LEDBuff[1]='
LEDBuff[2]='
LEDBuff[3]='
5.开放各模块中断
EnableSCIReInt();
(1)开放SCI接收中断
EnableTimer
(2);
(2)开放定时器1溢出中断
6.开放总中断
主循环
while
(1)
if(LightBuff!
=3)
不等于3表明PC机有命令发送过来,然后进行处理
Light_Change(Light_Run_PORT,Light_Run);
SCISend1(1,130);
发送串口的标志
SCISend1(1,LightBuff);
LightBuff=3;
if(LCDLen!
=0)接收在中断中进行
for(i=LCDLen;
32;
i++)为了满足32个字符
ShowBuff[i]='
*'
LCD显示MCU从串口接收到的32个数据
LCDshow((uint8*)ShowBuff);
SCISend1(1,131);
发送LCD的标志
SCISendN(1,32,ShowBuff);
发回给PC机
if(pwmDutyPC<
101)
{
PWM(1,0,0x800,pwmDutyPC);
Delay(10);
pwmDutyPC=101;
}
if(chanelNum<
30)
ma=(uint8)ADCAve(chanelNum,50);
SCISend1(1,137);
SCISend1(1,ma);
chanelNum=30;
LEDshow(LEDBuff);
第4章PC方程序控制
PC端程序以串口为核心,用户界面上划分多个区域,实现不同控制功能。
PC端用户界面如图4.1,4.2所示(因为界面太大,分为2幅图片截取)。
图4.1PC端程序界面
图4.2PC端程序界面
4.1串口数据接收与发送
串口接收数据子程序实现对于标志位的识别与处理,将MCU发送的数据进行分类,并且显示在用户界面上。
-----*
<
summary>
对象:
SCIPort*
事件:
DataReceived*
功能:
串口接收数据*
函数调用:
(1)SCIReceiveData,串口接收函数*
(2)SCIUpdateRevtxtbox,更新文本框中的内容*
paramname="
sender"
>
<
param>
e"
-----*
privatevoidSCIPort_DataReceived(objectsender,
System.IO.Ports.SerialDataReceivedEventArgse)
if(!
SCIPort.IsOpen)
this.TSSLState.Text="
串口没打开!
"
return;
Stringstr=String.Empty;
boolFlag;
标记串口接收数据是否成功
intlen;
标记接收的数据的长度
调用串口接收函数,并返回结果
Flag=sci.SCIReceiveData(SCIPort,refPublicVar.g_ReceiveByteArray);
if(Flag==true)
显示MCU端发来的数据,以便于调试
len=PublicVar.g_ReceiveByteArray.Length;
对于字符串形式,考虑到可能有汉字,
直接调用系统定义的函数,处理整个字符串
str=Encoding.Default.GetString(PublicVar.g_ReceiveByteArray);
if((this.TbShowString.Text).Length>
100)
this.TbShowString.Text=string.Empty;
this.TbShowDec.Text=string.Empty;
this.TbShowHex.Text=string.Empty;
SCIUpdateRevtxtbox(TbShowString,str);
十进制和十六进制形式按字节进行处理
for(inti=0;
i<
len;
i++)
data=PublicVar.g_ReceiveByteArray[i];
获取命令类型
SCIUpdateRevtxtbox(TbShowString,((char)data).ToString());
串口字符显示
十进制都是按照三位来显示,字节之间有空格表示区分
SCIUpdateRevtxtbox(TbShowDec,data.ToString("
D3"
)+"
"
);
十六进制都是按照两位来显示,字节之间有空格表示区分
SCIUpdateRevtxtbox(TbShowHex,data.ToString("
X2"
if(data>
=130&
data<
=150)
commandType=data;
准备使长度值=0
if(commandType==131)this.tbLCDOutput.Text=string.Empty;
if(commandType==132)this.tbMCUTime.Text=string.Empty;
if(commandType==137)this.tbADValue.Text=string.Empty;
continue;
if(commandType==130)
byteswKey=data;
获取开关状态数据
小灯和开关模块
if(swKey==1)注意:
这是硬件开关的状态不一定对应软件开关的状态。
=1,则亮,否则暗
this.btnSwKey.Image=Image.FromFile(Application.StartupPath+"
\\..\\..\\Pictures\\buttonOn.BMP"
this.btnLight.Image=Image.FromFile(Application.StartupPath+"
\\..\\..\\Pictures\\LightOn.BMP"
\\..\\..\\Pictures\\buttonOff.BMP"
\\..\\..\\Pictures\\LightOff.BMP"
elseif(commandType==131)
LCD测试模块
SCIUpdateRevtxtbox(tbLCDOutput,((char)data).ToString());
elseif(commandType==132)
timer模块
bytetmr=data;
tmrCount++;
tmrStr+=(tmrCount>
1?
:
:
)+(tmr<
10?
("
0"
+tmr.ToString()):
tmr.ToString());
if(tmrCount>
=3)
SCIUpdateRevtxtbox(tbMCUTime,tmrStr);
tmrCount=0;
tmrStr=string.Empty;
commandType=0;
elseif(commandType==133)
PWM测试模块
高端不作处理仅留一接口在此
elseif(commandType==134)
键盘测试模块
bytekbKey=data;
for(bytej=0;
j<
16;
j++)
if(KBBoard[j]==(char)kbKey)
kb[j].Image=Image.FromFile(Application.StartupPath+"
\\..\\..\\Pictures\\KeyDown.BMP"
KBi=j;
SCIUpdateRevtxtbox(tbKBShow,KBBoard[j].ToString());
break;
elseif(commandType==135)
LED测试模块
bytedtLED=data;
8;
复原
LEDOpr(ledCount,j,"
Off"
再根据条件使相应的条型变换
if(GetBit(ledTBL[dtLED],j))
On"
ledCount++;
if(ledCount>
=4)
ledCount=0;
elseif(commandType==137)
AD转换模块
intADValue=data;
SCIUpdateRevtxtbox(tbADValue,ADValue.ToString());
第5章总结与体会
通过本程序的编写与调试,了解了单片机设计的基础知识,熟悉了单片机的开发与调试过程,在实践中体会编程要领。
特别是将多个功能组合在一起时需要综合考虑MCU的资源利用问题,必须合理分配资源。
程序设计时解决了PWM与时钟共同使用定时器0的问题,解决了LCD显示与AD转换同时使用引脚PTB0的问题等。
设计过程中学会了一些设计思想和技巧,先将各个模块独立设计并验证其功能,最后将这些模块综合起来,有步骤地实现系统由小到大的过程。
设计与实现过程让自己学到许多知识,特别是遇到问题的时候学会的查找资料,网络上大量的资源都可以使用,只需要认真检索一定可以找到需要的内容。
设计系统需要信心也需要耐心,只有坚持不懈的努力才能完成任务。
第6章使用说明
本说明介绍一个FreescaleHC08单片机实验系统软件实例的使用步骤。
1.LCD显示验证,保持步骤1连线,将LCD显示器连接在实验箱默认接口上,写入字符,如正常显示说明LCD工作正常,如不显示请更换另一块LCD,如显示说明上一块LCD坏,如还不显示请检查MCU引脚是否正常。
2.与PC联机测试,请使用串口数据线将MCU与PC连接,打开PC端程序。
首先观察串口状态显示,是否已经为已连