综合应用设计
要求:
1)准时提交 A/B/C/D
2)作品完成度 A/B/C/D
3)自创硬件占比 A/B/C/D
以51单片机硬件开发板为基础,设计一套功能完整的作品,充分利用板上的各种硬件电路,以自创的代码将功能实现,并形成项目报告。
要求:
(1)基本部分:作品要利用CPU最小系统外至少5部分硬件电路以同时实现功能,包括但不限于LED、KB、BP、LCD、EEPROM、UART;
(2)创优部分:包括但不限于驱动外接模块、实现算法逻辑、自创硬件;
(3)源代码原创编写;
(4)项目报告必须对所设计的电子电路工作原理与关键的制作过程进行阐述,字体字数不限;
(5)项目报告必须有作品照片的附图,如设计失败,必须有相应的经验总结报告;
(6)源代码作为项目报告的附录;
(7)项目报告的封面采用深圳大学实验报告格式,实验名称自定。
main.c
#include <REGX52.H>
#include "Delay.h"
#include "math.h"
#include <INTRINS.H>
sbit Buzzer=P2^5; //蜂鸣器
void Delay(unsigned char xms) //延时函数
{
unsigned char i, j;
while(xms--)
{
_nop_();
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
}
/*********************************XPT2046*********************************/
sbit DIN = P3^4; //AD芯片
sbit CS = P3^5;
sbit DCLK = P3^6;
sbit DOUT = P3^7;
void input_AD_control(unsigned char control)
{
unsigned int i;
DCLK=0; //时钟初始是0
CS=0; //片选拉低
for(i=0; i<8; i++) //依次把数据发出去
{
DIN=control & (0x80 >> i) ;//和1000 0000相与,可以得到最高位,后面1依次向右移动,得到其余位
DCLK=1; //时钟上升沿发送DIN
DCLK=0;//发送完后拉低
}
}
unsigned int read_AD()
{
unsigned int i,AD_data=0;
DCLK=1;
DCLK=0; //观察时序图发现还要多一个时钟周期才可以读取数据
for(i=0; i<12; i++)
{
DCLK=1;
DCLK=0; //时钟下降沿DOUT接收数据
AD_data |= DOUT;
AD_data <<=1; //向左移,依次复制DOUT
}
CS = 1; //片选拉高,结束
return AD_data;
}
/*********************************XPT2046*********************************/
/**********************************EEPROM*********************************/
sbit SCL=P2^1;
sbit SDA=P2^0;
void start(void) //SCL高电平期间,SDA从高电平切换到低电平
{
SDA=1;
SCL=1;
SDA=0;
SCL=0;
}
void stop(void) //SCL高电平期间,SDA从低电平切换到高电平
{
SDA=0;
SCL=1;
SDA=1;
}
void send_byte(unsigned char byte)
{
unsigned char i;
for(i=0;i<8;i++) //重复八次,一个字节
{
SDA=byte&(0x80>>i); //和1000 0000相与,可以得到最高位,后面1依次向右移动,得到其余位
SCL=1; //SCL拉高,在高电平期间,读取数据
SCL=0; //拉高后马上拉低是可以的,手册上有高电平的时间要大于0.4微秒,足够了
}
}
unsigned char accepct_byte(void)
{
unsigned char i,byte=0x00;
SDA=1; //释放SDA
for(i=0;i<8;i++)
{
SCL=1; //SCL拉高之后读取数据
if(SDA) //数据在SDA
{
byte|=(0x80>>i); // 依次复制右移
}
SCL=0; //拉低结束读取
}
return byte;
}
void send_respond(bit one_or_zero) //在接收完一个字节之后,主机在下一个时钟发送一位数据,可以用bit
{
SDA=one_or_zero; //数据0表示应答,数据1表示非应答
SCL=1;
SCL=0;
}
unsigned char accept_respond(void) //在发送完一个字节之后,主机在下一个时钟接收一位数据
{
bit one_or_zero;
SDA=1; //先释放SDA
SCL=1; //SCL拉高后读取
one_or_zero=SDA; //数据0表示应答,数据1表示非应答
SCL=0;
return one_or_zero;
}
void eeprom_write(unsigned char address,infomation)
{
start();
send_byte(0XA0); //固定的,写
accept_respond();
send_byte(address);
accept_respond();
send_byte(infomation);
accept_respond();
stop();
}
unsigned char eeprom_read(unsigned char address)
{
unsigned char Data;
start();
send_byte(0XA0);
accept_respond();
send_byte(address);
accept_respond();
start();
send_byte(0XA1); //固定的,读
accept_respond();
Data=accepct_byte();
send_respond(1);
stop();
return Data;
}
/**********************************EEPROM*********************************/
/*********************************矩阵键盘********************************/
unsigned char get_keynumber() //扫描矩阵键盘,得到键值
{
unsigned char keynumber=0;
P1=0xFF;
P1_3=0;
if(P1_7==0){Delay(10);while(P1_7==0);Delay(10);keynumber=1;}
if(P1_6==0){Delay(10);while(P1_6==0);Delay(10);keynumber=5;}
if(P1_5==0){Delay(10);while(P1_5==0);Delay(21);keynumber=9;}
if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);keynumber=13;}
P1=0xFF;
P1_2=0;
if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);keynumber=2;}
if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);keynumber=6;}
if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);keynumber=10;}
if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);keynumber=14;}
P1=0xFF;
P1_1=0;
if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);keynumber=3;}
if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);keynumber=7;}
if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);keynumber=11;}
if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);keynumber=15;}
P1=0xFF;
P1_0=0;
if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);keynumber=4;}
if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);keynumber=8;}
if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);keynumber=12;}
if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);keynumber=16;}
return keynumber;
}
/*********************************矩阵键盘********************************/
/**********************************LCD1602********************************/
sbit RS=P2^6;
sbit RW=P2^5;
sbit EN=P2^7;
#define LCD_line P0
void LCD_delay() //LCD用延时函数
{
unsigned char i, j;
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
void LCD_write_command(unsigned char Command)
{
RS=0;
RW=0;
LCD_line=Command;
EN=1;
LCD_delay();
EN=0;
LCD_delay();
}
void LCD_write_data(unsigned char Data)
{
RS=1;
RW=0;
LCD_line=Data;
EN=1;
LCD_delay();
EN=0;
LCD_delay();
}
void LCD_set_light(unsigned char Line,unsigned char Column)
{
if(Line==1)
{
LCD_write_command(0x80|(Column-1));
}
else if(Line==2)
{
LCD_write_command(0x80|(Column-1+0x40));
}
}
void LCD_Init()
{
LCD_write_command(0x38);
LCD_write_command(0x0c);
LCD_write_command(0x06);
LCD_write_command(0x01);
}
void LCD_string_show(unsigned char Line,unsigned char Column,char *String)
{
unsigned char i;
LCD_set_light(Line,Column);
for(i=0;String[i]!='\0';i++)
{
LCD_write_data(String[i]);
}
}
int LCD_pow(int X,int Y)
{
unsigned char i;
int Result=1;
for(i=0;i<Y;i++)
{
Result*=X;
}
return Result;
}
void LCD_num_show(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i;
LCD_set_light(Line,Column);
for(i=Length;i>0;i--)
{
LCD_write_data(Number/LCD_pow(10,i-1)%10+'0');
}
}
/**********************************LCD1602********************************/
/***********************************主函数********************************/文章来源地址https://www.toymoban.com/news/detail-831983.html
unsigned int AD_data,keynumber,count,limit=1000,mode,read_data,lux,peak_lux,lowest_lux=100,i,j;
void main()
{
LCD_Init();
while(1) //一直在读取
{
input_AD_control(0xAC); //AD控制字输入
AD_data = read_AD(); //读取AD值
lux=(8.44*pow(10,-11))*pow(AD_data,3.962); //转换AD值为光强
keynumber=get_keynumber();
if (keynumber)
{
if(keynumber==13) //设置阈值
{
LCD_string_show(1,1,"set_limit_value ");
LCD_string_show(2,1," ");
mode=1;
limit=0;
count=0;
}
if(keynumber<=10 && mode==1) //当13被按下后,可以输入0-9的数字
{
if(count<5) //可以输入5位
{
limit*=10; //乘以10,左移一位
limit+=keynumber%10; //每次输入键值都加入个位
count++; // 从0加到4,后面就不能输入了
}
LCD_num_show(2,1,limit,5); //更新显示
}
if(keynumber==15) //清空阈值输入,重新输入阈值
{
limit=0;
count=0;
peak_lux=0;
LCD_num_show(2,1,limit,5); //更新显示
}
if(keynumber==16) //mode设置为2,后面可以显示光强了
{
mode=2;
}
if(keynumber==14) //eeprom写入光强峰值
{
mode=0;
LCD_string_show(1,1," "); //刷新屏幕
LCD_string_show(2,1," ");
eeprom_write(0,peak_lux%256);
Delay(10);
eeprom_write(1,peak_lux/256); //写入高八位和低八位
Delay(10); //延时以防出错
LCD_num_show(1,1,peak_lux,5);
LCD_string_show(2,1,"write lux_peak");
Delay(2000);
LCD_string_show(2,1," "); //刷新屏幕
}
if(keynumber==11) //eeprom写入光强谷值
{
mode=0;
LCD_string_show(1,1," "); //刷新屏幕
LCD_string_show(2,1," ");
eeprom_write(0,lowest_lux%256);
Delay(10);
eeprom_write(1,lowest_lux/256); //写入高八位和低八位
Delay(10); //延时以防出错
LCD_num_show(1,1,lowest_lux,5);
LCD_string_show(2,1,"write lux_lowest");
Delay(2000);
LCD_string_show(2,1," "); //刷新屏幕
}
if(keynumber==12) //读取eeprom
{
mode=0;
read_data=eeprom_read(0);
read_data|=eeprom_read(1)<<8;
LCD_string_show(1,1," ");
LCD_num_show(1,1,read_data,5);
LCD_string_show(2,1,"read lux_H_L ");
Delay(2000); //等一段时间
LCD_string_show(2,1," "); //刷新屏幕
}
}
if (mode == 2) //显示光强
{
LCD_string_show(1,1,"AD lux ");
LCD_num_show(2,1,AD_data,5);
LCD_num_show(2,7,lux,5);
if (lux>=limit) //如果光强超出阈值
{
for(j=0;j<10;j++) //蜂鸣器响
{
Buzzer=~Buzzer;
_nop_();
i = 247;
while (--i);
}
}
if (lux > peak_lux) // 如果新的lux值大于当前的峰值
{
peak_lux = lux; // 更新峰值
}
if (lux <lowest_lux)// 如果新的lux小于当前的峰值
{
lowest_lux=lux; // 更新峰值
}
}
}
} 文章来源:https://www.toymoban.com/news/detail-831983.html
/***********************************主函数********************************/
到了这里,关于单片机综合应用设计的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!