
module mul3_testbench ; //定义一个没有输入输出端口的测试平台
reg a2,a1,a0,b2,b1,b0; //被测模块的input端口,改为对应的 reg寄存器做输入信号
wire p5,p4,p3,p2,p1,p0; //被测模块的output端口,改为对应的wire型
initial begin // 初始化所有 输入信号的寄存器值
a2= 0;
a1=0;
a0 =0;
b2 =0;
b1= 0;
b0 =0;
#50 //一般延迟较长时间后,应该使复位信号不复位系统正常工作,但你没有复位信号
end
// 初始化模块结束后一般时序电路仿真是产生时钟信号,
//这是纯组合逻辑没有时钟信号就省略了
//然后就可以根据你所需要验证的功能在此位置编写initial块或always块给reg 型
//的输入信号赋值的相关逻辑,观察wire型输入信号的值
//---------------------------调用被测对象,格式如一般元件调用-------------------
mul3 DUT( a2(a2),
a1(a2),
a0(a0),
b2(b2),
b1(b2),
b0(b0),
p5(p5),
p4(p4),
p3(p3),
p2(p2),
p1(p1),
p0(p0)
);
endmodule
// 最后的提示,你的程序里定义了整数型变量,其实是不好的用法,甚至不能被正确综合,
//可以用等值的reg 型变量来替代,即使你定义成整数型,实际上也是被综合成reg型的,
//另外,一般可综合代码中最好不要用for语句,个人认为你的代码会完全功能不正常的
#include"reg52h"
#include"intrinsh"
#define uchar unsigned char //无符号8位
#define uint unsigned int //无符号16位
#define ulong unsigned long //无符号32位
sbit K1=P1^0; //按下K1后,开始测距
sbit LEDRed=P1^1; //测距指示灯,亮表示正在测距,灭表示测距完成
//sbit BEEP=P1^2; //报警测量超出范围
sbit Trig=P2^5; //HC-SR04触发信号输入
sbit Echo=P2^6; //HC-SR04回响信号输出
float xdata DistanceValue=00; //测量的距离值
float xdata SPEEDSOUND; //声速
float xdata XTALTIME; //单片机计数周期
uchar xdata stringBuf[6]; //数值转字符串缓冲
//LCD1602提示信息
uchar code Prompts[][16]=
{
{"Measure Distance"}, //测量距离
{"- Out of Range -"}, //超出测量范围
{"MAX range 400cm "}, //测距最大值400cm
{"MIN range 2cm "}, //测距最小值2cm
{" "}, //清屏
{" Press K1 Start "} //按键开始测量
};
uchar xdata DistanceText[]="Range: "; //测量结果字符串
uchar xdata TemperatureText[]="Temperature: ";//测量温度值
extern void LCD_Initialize(); //LCD初始化
extern void LCD_Display_String(uchar , uchar); //字符串显示
extern void ReadTemperatureFromDS18B20(); //从DS18B20读取温度值
extern int xdata CurTempInteger;
//毫秒延时函数
void DelayMS(uint ms);
//20微秒延时函数
void Delay20us();
//HCSR04初始化
void HCSR04_Initialize();
//测量距离
float MeasuringDistance();
//测距的数值排序求平均
float DistanceStatistics();
//输出距离值到LCD1602上
void DisplayDistanceValue(float dat);
//将无符号的整数转成字符串,返回字符串长度,不包括'\0'结束符
uchar UnsigedIntToString(uint value);
//蜂鸣器
//void Beep(uchar time);
//显示温度值
void DisplayTemperatureValue();
void main()
{
LCD_Initialize();//LCD1602初始化
LCD_Display_String(Prompts[0],0x00);
LCD_Display_String(Prompts[5],0x40);
ReadTemperatureFromDS18B20(); //测温度
HCSR04_Initialize(); //HC-SR04初始化
while(1)
{
if(K1==0)
{
DelayMS(5);
if(K1==0)
{
//Beep(1);
while(K1==0);
LEDRed=0;
ReadTemperatureFromDS18B20();//测温度
DisplayTemperatureValue();
if(CurTempInteger<14)
CurTempInteger=14;
else if(CurTempInteger>26)
CurTempInteger=26;
SPEEDSOUND=3341+CurTempInteger061;//计算声速
DistanceValue=DistanceStatistics(); //测距并返回距离值
DisplayDistanceValue(DistanceValue); //显示距离值
LEDRed=1;
}
}
}
}
//测距的数值排序求平均
float DistanceStatistics()
{
uchar i,j;
float disData[7],t;
//连续测距
for(i=0;i<7;i++)
{
disData=MeasuringDistance();
DelayMS(80);
}
//排序
for(j=0;j<=6;j++)
{
for(i=0;i<7-j;i++)
{
if(disData>disData[i+1])
{
t=disData;
disData=disData[i+1];
disData[i+1]=t;
}
}
}
return (disData[2]+disData[3]+disData[4])/3;
}
//测量距离
float MeasuringDistance()
{
//最大定时时间约65ms
TH0=0;
TL0=0;
//生成20us的脉冲宽度的触发信号
Trig=1;
Delay20us();
Trig=0;
//等待回响信号变高电平
while(!Echo);
TR0=1; //启动定时器0
//等待回响信号变低电平
while(Echo);
TR0=0; //关闭定时器0
//返回距离值(mm)
return (SPEEDSOUNDXTALTIME((float)TH0256+(float)TL0))/2000;
}
//HCSR04初始化
void HCSR04_Initialize()
{
//计算单片机计数周期 晶振=11953M 单位us
XTALTIME=12/11953;
//温度25度时声速的值
SPEEDSOUND=3341+25061;
Trig=0;
Echo=0;
TMOD=0x01;
}
//输出距离值到LCD1602上
void DisplayDistanceValue(float dat)
{
uchar i=0,j=0,len;
uint value;
value=(uint)dat;
//范围检查大于4000mm和小于20mm都为超出测量范围
if(value>4000)
{
LCD_Display_String(Prompts[1],0x00);
LCD_Display_String(Prompts[2],0x40);
//Beep(2);
}
else if(value<20)
{
LCD_Display_String(Prompts[1],0x00);
LCD_Display_String(Prompts[3],0x40);
//Beep(2);
}
else
{
//将数值转换成字符串
len=UnsigedIntToString(value);
//保留1位小数
while(stringBuf!='\0')
{
if(len-j==1)
{
DistanceText[6+j]='';
j++;
}else
{
DistanceText[6+j]=stringBuf;
i++;
j++;
}
}
DistanceText[6+j]='c';
j++;
DistanceText[6+j]='m';
i=7+j;
//剩余位置补空格
while(i<16)
{
DistanceText=' ';
i++;
}
//LCD_Display_String(Prompts[0],0x00);
LCD_Display_String(DistanceText,0x40);
}
}
//显示温度值
void DisplayTemperatureValue()
{
TemperatureText[13]=CurTempInteger/10+'0';
TemperatureText[14]=CurTempInteger+'0';
TemperatureText[15]='C';
LCD_Display_String(TemperatureText,0x00);
}
//将无符号的整数转成字符串,返回字符串长度
uchar UnsigedIntToString(uint value)
{
uchar i=0,t,length;
//从个位开始转换
do
{
stringBuf='0'+value;
value=value/10;
i++;
}while(value!=0);
length=i;
//将字符串颠倒顺序
for(i=0;i<(length/2);i++)
{
t=stringBuf;
stringBuf=stringBuf[length-i-1];
stringBuf[length-i-1]=t;
}
stringBuf[length]='\0';
return length;
}
//蜂鸣器
//延时函数 毫秒 @12000MHz
void DelayMS(uint ms)
{
uchar i, j;
while(ms--)
{
_nop_();
i = 2;
j = 239;
do
{
while (--j);
}while (--i);
}
}
//延时函数 20微秒 @12000MHz
void Delay20us()
{
uchar i;
_nop_();
i = 7;
while (--i);
}
//定时器0中断
void Timer0() interrupt 1
{
}
//DS18B20代码:
#include
#include
#define uchar unsigned char //无符号8位
#define uint unsigned int //无符号16位
//定义DS18B20端口DS18B20_DQ
sbit DS18B20_DQ = P2^7;
//当前采集的温度值整数部分
int xdata CurTempInteger;
//当前采集的温度值小数部分
int xdata CurTempDecimal;
void Delayus(uint count)
{
while (--count);
}
uchar Reset_DS18B20()
{
uchar status;
DS18B20_DQ=1;
Delayus(1);
//开始复位过程
DS18B20_DQ=0; //数据线拉低
Delayus(100); //延时480us-960us
DS18B20_DQ=1; //数据线拉高
Delayus(10); //延时15us-60us
status=DS18B20_DQ; //读取数据线上的状态
Delayus(120);
return status;
}
void WriteByteToDS18B20(uchar dat)
{
uchar i;
for(i=0;i<8;i++)
{
DS18B20_DQ=0;
DS18B20_DQ=dat&0x01; //发送1位数据
Delayus(15); //延时60us以上
DS18B20_DQ=1; //释放总线,等待总线恢复
dat>>=1; //准备下一位数据
}
}
uchar ReadByteFromDS18B20()
{
uchar i,dat=0;
for(i=0;i<8;i++)
{
DS18B20_DQ=0; //拉低总线,产生读信号
dat>>=1;
DS18B20_DQ=1; //释放总线,准备读1位数据
Delayus(2); //延时4us
if(DS18B20_DQ) dat|=0x80; //合并每位数据
Delayus(15); //延时60us
DS18B20_DQ=1; //拉高总线,准备读下1位数据
}
return dat;
}
void ReadTemperatureFromDS18B20()
{
uchar flag=0;//正负符号标志
//存储当前采集的温度值
uchar TempValue[]={0,0};
if(Reset_DS18B20())
{
CurTempInteger=255;
CurTempDecimal=0;
}
else
{
WriteByteToDS18B20(0xCC);//跳过ROM命令
WriteByteToDS18B20(0x44);//温度转换命令
Reset_DS18B20();//复位
WriteByteToDS18B20(0xCC);//跳过ROM命令
WriteByteToDS18B20(0xBE);//读取温度暂存器命令
TempValue[0]=ReadByteFromDS18B20();//先读低字节温度值
TempValue[1]=ReadByteFromDS18B20();//后读高字节温度值
Reset_DS18B20();//复位
//计算温度值
//先进行正温度与负温度判断,高5位全为1(0xF8)则为负数
if((TempValue[1]&0xF8)==0xF8)
{
//负温度计算:取反加1,低字节为0时,高字节取反加1,否则不需要。
TempValue[1]=~TempValue[1];
TempValue[0]=~TempValue[0]+1;
if(TempValue[0]==0x00) TempValue[1]++;
flag=1;//负数标志
}
//将温度值分为整数和小数两部分存储(默认为12位精度)
CurTempInteger=((TempValue[1]&0x07)<<4)|((TempValue[0]&0xF0)>>4); if(flag) CurTempInteger=-CurTempInteger;
CurTempDecimal=(TempValue[0]&0x0F)625;
}
}
//LCD1602程序代码:
#include
#include
#define uchar unsigned char
#define uint unsigned int
#define Delay4us(){_nop_();_nop_();_nop_();_nop_();}
sbit LCD_RS=P2^0;
sbit LCD_RW=P2^1;
sbit LCD_EN=P2^2;
void LCDDelay(uint ms)
{
uchar i, j;
while(ms--)
{
_nop_();
i = 2;
j = 239;
do
{
while (--j);
}while (--i);
}
}
bit LCD_Busy_Check()
{
bit result;
LCD_RS=0; LCD_RW=1; LCD_EN=1;
Delay4us();
result=(bit)(P0&0x80);
LCD_EN=0;
return result;
}
void Write_LCD_Command(uchar cmd)
{
while(LCD_Busy_Check());
LCD_RS=0; LCD_RW=0; LCD_EN=0; _nop_(); _nop_();
P0=cmd; Delay4us();
LCD_EN=1; Delay4us(); LCD_EN=0;
}
void Write_LCD_Data(uchar dat)
{
while(LCD_Busy_Check());
LCD_RS=1;LCD_RW=0;LCD_EN=0;
P0=dat;Delay4us();
LCD_EN=1;Delay4us();LCD_EN=0;
}
void LCD_Set_POS(uchar pos)
{
Write_LCD_Command(pos|0x80);
}
void LCD_Initialize()
{
Write_LCD_Command(0x01); LCDDelay(5);
Write_LCD_Command(0x38); LCDDelay(5);
Write_LCD_Command(0x0C); LCDDelay(5);
Write_LCD_Command(0x06); LCDDelay(5);
}
void LCD_Display_String(uchar str, uchar LineNo)
{
uchar k;
LCD_Set_POS(LineNo);
for(k=0;k<16;k++)
{
Write_LCD_Data(str[k]);
}
}
void LCD_Display_OneChar(uchar Dat, uchar X, uchar Y)
{
Y &= 0x01; //限制Y不能大于1(2行,0-1)
X &= 0x0F; //限制X不能大于15(16个字符,0-15)
if(Y) {X |= 0x40;} //当要在第二行显示时地址码+0x40;
X |= 0x80; //算出指令码
Write_LCD_Command(X);
Write_LCD_Data(Dat);
}
1、如果仿真一个传递函数的阶跃、脉冲等响应,可以直接使用matlab函数。
2、如果是一个复杂的系统,需要使用matlab中的Simulink工具箱。
3、仿真方法,仿真(s+1)/(2s^2+2s+1)的阶跃响应
num=[1
1];
den=[2
2
1];
f=tf(num,den)
Transfer
function:
s
+
1
2
s^2
+
2
s
+
1
>>
step(f)
这样就可以得到它的响应曲线。
一、代码写的也很清楚,问题也很明白。先说一下你这个程序想完成的功能吧:
P0口的数码管属于后台程序,他一直循环计数 0~8 。他能被任何一个中段所打断,并且该中断退出后,P0口的数码管能接着被打断之前的数字继续计数,而不是从 0 重新开始,这一点你的程序没有做到。
P2口的数码管由 INT0 中断控制,中断一次,只完成一次 0~8 的计数。他可以打断 P0 口,而不能打断 P1 口,因为 INT0 的优先级低。如果 INT0 被 INT1 打断了,INT1 退出后,INT0 应接着原来的数继续计数,而不是 INT1 退出之后,INT0 不会动了,这一点你的程序也没做到。
P1口的数码管由 INT1 中断控制,中断一次,也完成一次 0~8 的计数。他可以打断 P0口,也可以打断 P2口(INT0),他退出之后,被中断的程序应该恢复之前的工作。
这些问题都是由于在中断服务程序中,没有对现场进行保护引起的。问题找到了,解决方法很简单,就是在每个中断服务程序中加上现场保护就行了,即在每个中断服务程序的开始各加一条语句“PUSH ACC”即可,现场恢复你的程序里边有。
二、下面是修改过的程序,并按照题目的要求添加了注释
ORG 0000HSJMP STAR
ORG 0003H
SJMP INT0S
ORG 0013H
SJMP INT1S
ORG 0030H
STAR:
MOV IE,#85H //中断允许
MOV TCON,#05H //低电平触发中断
MOV P3,#0FFH //P3口拉高,为两个按钮服务
SETB PX1 //提高 INT1 的优先级
ST0:
MOV A,#1 //立即数 1 送 A,准备读 0 的段码
ST1:
PUSH ACC //入栈保存
ACALL SEG7 //去读段码
MOV P0,A //送 P0 口显示
ACALL DELAY //延时一小会
POP ACC //把保存的 立即数d回 A
INC A //A 自身加 1,为读取下一个段码做准备
CJNE A,#10,ST1 // A=10:往下走,否则转到ST1
SJMP ST0 //开始下一轮 0~8 的显示
INT0S:
PUSH ACC //该句是添加的,用于现场保护
MOV A,#0
LOOP:
INC A
PUSH ACC
ACALL SEG7
MOV P2,A
POP ACC
ACALL DELAY
CJNE A,#9,LOOP
POP ACC //原来就有,用于现场恢复
MOV P2,#0FFH
RETI
INT1S:
PUSH ACC //这句也是现场保护
MOV A,#0
LOOP1:
INC A
PUSH ACC
ACALL SEG7
MOV P1,A
POP ACC
ACALL DELAY
CJNE A,#9,LOOP1
MOV P1,#0FFH
POP ACC //现场回复
RETI
DELAY:
MOV R7,#250
D1:
MOV R6,#250
D2:
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
DJNZ R6,D2
DJNZ R7,D1
RET
SEG7:
MOVC A,@A+PC
RET //这条语句一字节,所以执行上句之前 A 要加 1
DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H
END
如果感到满意,你就跺跺脚,踩------纳!!!!!
以上就是关于关于verilog的仿真测试程序编写全部的内容,包括:关于verilog的仿真测试程序编写、1602显示超声波测距的C语言程序和Proteus仿真图、如何用matlab进行系统仿真等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)