单片机综合应用设计

综合应用设计

要求:

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********************************/

/***********************************主函数********************************/

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; // 更新峰值

       }

      

    }

    }

}     

/***********************************主函数********************************/

  • 7
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
51单片机经典毕业设计CSND是一个非常常见的题目,在51单片机开发领域非常有价值的经典项目。 CSND是指中国软件开发网(China Software Development Network),对于51单片机而言,可以理解为基于51单片机开发的毕业设计项目。 在CSDN中,经典的51单片机毕业设计有很多种选择,以下是一些建议: 1. 智能交通信号灯控制系统:利用51单片机和传感器技术,实现交通信号灯的智能控制,可以根据交通流量自动调节信号灯的时间,提高交通效率。 2. 温湿度监控与控制系统:使用51单片机和温湿度传感器,实时监控环境中的温度和湿度,可以通过LCD显示屏显示结果,并可以根据设定的阈值自动控制空调、加湿器等设备。 3. 智能家居控制系统:基于51单片机和无线通信模块,实现家庭内各种电器设备的远程控制和自动化控制,比如通过手机App控制灯光、窗帘、空调等,实现智能家居的概念。 4. 迷宫小车控制系统:使用51单片机和多个红外传感器,设计一个能够自动寻找出口的小车,通过避障和路径规划算法,使小车能够在迷宫中自主探索并找到最短路径。 这些毕业设计项目都是基于51单片机的经典项目,通过实际操作和编程,可以提高对51单片机的理解和应用能力,对于毕业生的技术水平和综合能力的考核非常有帮助。同时,这些项目的实践与应用背景也非常广泛,可以在实际生活中具有一定的应用价值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值