硬件设计
链接:https://pan.baidu.com/s/1qwUpJ8yay8eiYCjmHuftQQ
提取码:6mfd
代码设计
#include"reg51.h" //此文件中定义了单片机的一些特殊功能寄存器
#include"math.h"
#define PI 3.14
sbit P36=P3^6; //P36=0是单片机2数据发送完毕的标志
sbit P37=P3^7; //P37=0是单片机1数据发送完毕的标志
sbit RST=P3^2;
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
u8 N=90; //N为多少,即一个周期内采样多少个点
u16 k;
u8 value;
u8 x;
u8 j=1;
u8 KeyValue; //用来存放读取到矩阵键盘的键值
u8 count=0;
u16 xdata sin_100[90]; //正弦信号数组
u8 dis_buf[4];
u8 code led_data[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, //数码管段选
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //数码管段选0-F
u8 code led_bit[4]={0xf7,0xfb,0xfd,0xfe}; //数码管位选
void delay(u16 i) // delay延时函数 i=1时,大约延时10us
{
while(i--);
}
void KeyDown(void) //该函数用于检测是否有按键按下并读取键值
{
char a=0;
P0=0x0f; //高四位为0,低四位为1,当按键被按下后,会有某个低四位变为0
if(P0!=0x0f)//读取按键是否按下
{
delay(100);//延时10ms进行消抖
if(P0!=0x0f)//再次检测键盘是否按下
{
//测试列
P0=0X0F;
switch(P0) //按键被按下后,会有某个低四位变为0
{
case(0X07): KeyValue=0;break; //P0.3=0,即第一列有某个按键被按下
case(0X0b): KeyValue=1;break; //P0.2=0,即第二列有某个按键被按下
case(0X0d): KeyValue=2;break; //P0.3=0,即第三列有某个按键被按下
case(0X0e): KeyValue=3;break; //P0.4=0,即第四列有某个按键被按下
}
//测试行
P0=0XF0;
switch(P0)
{
case(0X70): KeyValue=KeyValue;break; //P0.7=0,即第一行有某个按键被按下
case(0Xb0): KeyValue=KeyValue+4;break; //……每行相差4,因此为+4
case(0Xd0): KeyValue=KeyValue+8;break;
case(0Xe0): KeyValue=KeyValue+12;break;
}
}
}
}
void sin_initial(void) //正弦信号数组初始化
{
for(k=0;k<N;k++) //N为多少,即一个周期内采样多少个点
{sin_100[k]=100+100*sin(2*k*PI/50); }
}
void serial_initial(void) //串口初始化 //T1作为波特率发生器,使用工作模式1
{
TMOD=0x20; //T1工作方式2八位定时器自动重装
TH1=0xf4;
TL1=0xf4; // 波特率2400b/s
TR1=1; //启动定时器1
SCON=0x40; //设定串口方式1
REN=1;
}
void Timer0Init() //定时器0初始化
{
TMOD|=0X01; //选择为定时器0模式,工作方式1,仅用TR0打开启动。
TH0=0Xff;
TL0=0Xff; //给定时器赋初值,定时1ms
ET0=1;//打开定时器0中断允许
EA=1;//打开总中断
TR0=1;//打开定时器
}
void send_byte(u8 x) //串口发送一个字节
{
SBUF=x; //启动串口发送
while(TI==0);
TI=0; //发送完毕,置位TI=0
delay(1);
}
void main() //主函数
{
P0=0x0f;
while(P0==0x0f);
KeyDown();
switch(KeyValue)
{
case(0):N=15;break; //按下K0,N为15,即一个正弦信号周期内采样15个点
case(1):N=20;break; //按下K1,N为20,即一个正弦信号周期内采样20个点
case(2):N=25;break; //按下K2,N为25,即一个正弦信号周期内采样25个点
case(3):N=30;break; //按下K3,N为30,即一个正弦信号周期内采样30个点
case(4):N=35;break; //按下K4,N为35,即一个正弦信号周期内采样35个点
case(5):N=40;break; //按下K5,N为40,即一个正弦信号周期内采样40个点
case(6):N=45;break; //按下K6,N为45,即一个正弦信号周期内采样45个点
case(7):N=50;break; //按下K7,N为50,即一个正弦信号周期内采样50个点
case(8):N=55;break; //按下K8,N为55,即一个正弦信号周期内采样55个点
case(9):N=60;break; //按下K9,N为60,即一个正弦信号周期内采样60个点
case(10):N=65;break; //按下K10,N为65,即一个正弦信号周期内采样65个点
case(11):N=70;break; //按下K11,N为70,即一个正弦信号周期内采样70个点
case(12):N=75;break; //按下K12,N为75,即一个正弦信号周期内采样75个点
case(13):N=80;break; //按下K13,N为80,即一个正弦信号周期内采样80个点
case(14):N=85;break; //按下K14,N为85,即一个正弦信号周期内采样85个点
case(15):N=90;break; //按下K15,N为90,即一个正弦信号周期内采样90个点
default:break;
}
serial_initial(); //串口初始化
sin_initial(); //正弦信号数组初始化
Timer0Init(); //定时器0初始化
while(1)
{
if(j==1&&P36==0) //j==1只执行一次
{ //P36=0为单片机2开始发送数据标志
delay(100);
while(RI==0);
RI=0;
value=SBUF; //存储接受单片机2的数据(单片机2所接受的字节数)
P36=1;
j=0;
}
//单片机1用三位数码管显示字节数
dis_buf[0] =value%10; // 数码管"个位"
dis_buf[1] =value%100/10; // 数码管"十位"
dis_buf[2] =value/100; // 数码管"百位"
for(k=0;k<3;k++)
{ P1=led_bit[k]; //发送数码管位码到P1口
P2=led_data[dis_buf[k]]; //发送数码管段码到P2口
delay(1);
P2=0x00;
}
};
}
void Timer0() interrupt 1
{
// TH0=0XFF; //给定时器赋初值
// TL0=0XFF;
P37=0; //单片机1开始发送数据标志
for(k=0;k<N;k++)
{
send_byte(sin_100[k]);
}
P37=1; //单片机1结束发送数据标志
EA=0; //关闭总中断
TF0=0; //关闭溢出中断
TR0=0; //关闭定时器T0
}