钜形不锈钢水箱 发表于 2024-8-18 18:37:08

51单片机嵌入式开发:21、STC89C52R控制抢答器+数码管+背景表现+LCD1602x显

配套步伐


配套步伐
https://i-blog.csdnimg.cn/direct/8ed761bbea62413cbe711d6ec7a54df4.png
STC89C52R控制抢答器+数码管+背景表现+LCD1602x表现

1 概述

1.1 项目概述

该项目旨在使用STC89C52R单片机构建一个多功能抢答器表现系统,涵盖LCD1602x表现屏、数码管和背景数码表现器。通过串口通讯,单片机可以或许与背景数码表现器进行数据交换和控制,实现更加机动和多样化的表现功能。
1.2 项目构成部分

(1)STC89C52R单片机:
(2)LCD1602表现:
(3)数码管:
(4)背景数码表现器(通过串口通讯):
(5)按键:
(6)Proteus:
https://i-blog.csdnimg.cn/direct/ea8323da37174d1b8f7db3cac4853a28.png
1.3 功能描述

(1)LCD1602:
LCD1602表现屏用于展示笔墨信息,可以或许表实际时数据如日期、时间、温度等。
(2)数码管:
数码管用于出现数字信息,例如计数器数值、计时器时间等。
背景数码表现器(通过串口通讯):
借助串口通讯,单片机与背景数码表现器相连,实现双向数据传输和控制,扩展表现功能。
(3)按键:
通过4个按键实现抢答器按钮功能。
(4)Proteus:
使用实物演示和Proteus仿真方式展示系统功能。
2 开发环境

2.1 支持设备

我们采用华晴51开发板、Keil开发工具和PROTEUS仿真软件。结合这三者,开发人员得以进行完整的嵌入式系统开发流程。他们可以使用Keil开发工具编写、编译和调试8051单片机步伐,接着通过PROTEUS仿真软件验证步伐正确性和系统功能。一旦验证通过,步伐可下载至华晴51开发板进行实际硬件调试和测试,完成嵌入式系统的开发。这些工具的综合运用使得开发人员可以或许全面开发和验证嵌入式系统,提拔开发效率、降低成本,并确保系统的稳定性和可靠性。
(1)华晴51开发板:
华晴51开发板是一款基于8051系列单片机的专用开发板,主要用于嵌入式系统的学习、开发和测试。该开发板拥有多样的外设接口,包罗LED、按键、数码管、LCD表现屏、通讯接口等,使用户可以或许轻松进行各种实行和项目开发。此外,华晴51开发板支持多种编程方式,如汇编语言、C语言等,适用于各类用户,无论是初学者还是专业开发人员。
(2)Keil开发工具:
Keil开发工具是一套专业的嵌入式系统开发工具,主要针对ARM和8051等处置惩罚器的嵌入式软件开发。此中,Keil C51是专为8051系列单片机筹划的C语言集成开发环境,提供编译、调试、仿真等功能,使开发人员可以或许高效进行嵌入式软件开发。该工具配备了强大的调试功能,可帮助开发人员快速定位和解决步伐中的问题,提拔开发效率。
(3)PROTEUS仿真软件:
PROTEUS是一款被广泛应用于电子电路筹划和仿真的软件。在嵌入式系统开发范畴,PROTEUS通常用于对电路筹划和单片机步伐进行仿真,以验证系统功能、调试步伐并检测潜在问题。该软件提供了丰富的元件库和仿真功能,使用户可以或许轻松搭建电路原理图、加载单片机步伐,并进行实时仿真。
2.2 硬件电路

(1)STC89C52R单片机:
https://i-blog.csdnimg.cn/direct/0664a77b6a67429b8b4f8b536d5135d5.png
晶振使用11.0592Mhz
https://i-blog.csdnimg.cn/direct/2c02c40aa9b643c191f8a00136fac808.png
(2)LCD1602码表:
https://i-blog.csdnimg.cn/direct/847fe1541ff844c99fba193d46f032d8.png
(3)数码管:
https://i-blog.csdnimg.cn/direct/3eb46badd10e45bbb57d9521cd715096.png
(4)背景数码表现器(通过串口通讯):
https://i-blog.csdnimg.cn/direct/29ad16cb06f345a29296fae17f00e712.png
(5)按键:
按键使用独立按键情势,P34 P35 P36 P37引脚
https://i-blog.csdnimg.cn/direct/ba0986972ef14a1b8eb0be832451e092.png
(6)实物与Proteus:
https://i-blog.csdnimg.cn/direct/48bcf53e8d9e495a9a87a3102bb6d9e1.png
https://i-blog.csdnimg.cn/direct/e4442ae814564ffb8ac842a270070e8d.png
3 软件代码工程

//main.c文件
#include "includes.h"



/******************************************************************/
/*                  微秒延时函数//10us                         */
/******************************************************************/
void delay_us(unsigned int us)//delay us
{
        while(us--)
        {
        }
}

/******************************************************************/
/*                  微秒延时函数                              */
/******************************************************************/
void delay_ms(unsigned int Ms)//delay us
{
        while(Ms--)
        {
                delay_us(100);
        }
}





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


unsigned char pro_key_data = 0;

void main (void)
{
        char Test2[] = "                ";
        unsigned char databuf = {0};
        //串口外设初始化
        sys_uart_init();
        //LCD1602显示屏初始化
        LCD_init();   
        sprintf(Test2,"Nunber:");
        LCD_write_strl(0,0,Test2,16);
        P1 = 0xFF;
    while (1)
    {
                //获取按键值
                pro_key_data = sys_key_single();
               
               
               
                if(pro_key_data)
                {
                        //指示灯显示
                        P1 &= ~(1<<(pro_key_data-1));
                       
                        //数码管显示
                        sys_keynum_ledon(pro_key_data,0);
                       
                       
                        //LCD1602显示
                        LCD_write_com(0x80+7);
                        lcd_number(pro_key_data);
                }
    }
}
//includes.h文件
#ifndef __INCLUDES_H__
#define __INCLUDES_H__

//#include<reg52.h>

#include<intrins.h> //汇编指令_nop_
#include<stdio.h>         //标准输入输出

//_nop_(); 产生一条NOP指令
//作用:对于延时很短的,要求在us级的,采用“_nop_”函数,这个函数相当汇编NOP指令,延时几微秒。
//NOP指令为单周期指令,可由晶振频率算出延时时间。

//8051 为每个机器周期 12 时钟
//对于12M晶振,延时1uS。
//11.0592M晶振,延时1.0851uS。

//对于延时比较长的,要求在大于10us,采用C51中的循环语句来实现。


//包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include "STC89C5xRC_RDP.h"

//应用层头文件
//#include "c51_gpio.h"
#include "c51_ledtube.h"
#include "c51_key.h"
//#include "c51_timer.h"
//#include "c51_exit.h"
#include "c51_lcd1602.h"
//#include "c51_iic.h"
//#include "c51_tx1838.h"
#include "c51_uart.h"
//#include "c51_28byj48.h"
//#include "c51_ds1302.h"

extern unsigned char pro_key_data;



extern void delay_us(unsigned int us);//delay us;
extern void delay_ms(unsigned int Ms);//delay Ms;




#endif
//c51_ledtube.c文件
#include "includes.h"

显示段码值01234567,可对应原理图查看显示不同图形对应的引脚高点电平配置状态
//unsigned char const EL[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//0-F

code unsigned char ledmap[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x40,0x80};


///********************************************************
//函数名称:sys_ledtube_on1
//函数功能:点亮一个数码管全为亮起来
//入口参数:
//出口参数:
//修    改:
//内    容:
//********************************************************/
//void sys_ledtube_on1(void)
//{
//        //根据原理图,将P0口全部输出高电平,P2选择0号数码管
//        P0=0xFF;//取显示数据,段码
//        P2=0;        //取位码
//}

///********************************************************
//函数名称:sys_ledtube_on2
//函数功能:显示一组数据
//入口参数:
//出口参数:
//修    改:
//内    容:
//********************************************************/
//static unsigned char ledtube_cnt = 0;

//void sys_ledtube_on2(void)
//{
//        ledtube_cnt++;
//        if(ledtube_cnt>7)
//        {
//                ledtube_cnt = 0;
//        }
//        P0 = 0x00;                                //防止切换数码管瞬间有虚影出现
//        P2 = 0x00;
//        P0 = ledmap;        //取显示数据,段码
//        P2 = ledtube_cnt;                //取位码
//       
//        //根据人眼适应虚影缓冲时间为50ms左右
//        //我们调整delay在500以下可以看到明显的看起来是一串数据一起显示
//        delay(100);                        
//}


///********************************************************
//函数名称:sys_keynum_ledon
//函数功能:显示按键数值
//入口参数:按键数值
//出口参数:
//修    改:
//内    容:
//********************************************************/
void sys_keynum_ledon(unsigned char num,unsigned char pn)
{
        //根据原理图,将P0口全部输出高电平,P2选择0号数码管
        P0 = 0x00;                //防止切换数码管瞬间有虚影出现
        P2 = pn;                //取位码
        P0 = ledmap;        //取显示数据,段码
        delay_ms(1);
       
       
        P2 = 7;                //取位码
}
//c51_ledtube.h文件
#ifndef __C51_LEDTUBE_H__
#define __C51_LEDTUBE_H__


//extern unsigned char const EL[];

//extern void sys_ledtube_on1(void);
//extern void sys_ledtube_on2(void);

extern void sys_keynum_ledon(unsigned char num,unsigned char pn);


#endif
//c51_uart.c文件
#include "includes.h"



/*-----------------------------------------------
名称:串口通信
内容:连接好串口或者usb转串口至电脑,下载该程序,打开电源
      打开串口调试程序,将波特率设置为9600,无奇偶校验
      晶振11.0592MHz,发送和接收使用的格式相同,如都使用
      字符型格式,在发送框输入 hello,I Love MCU ,在接
      收框中同样可以看到相同字符,说明设置和通信正确
------------------------------------------------*/
                  


/******************************************************************/
void sys_uart_init(void)
{


        SCON= 0x50;                        /* SCON: 模式 1, 8-bit UART, 使能接收         */
        TMOD |= 0x20;               /* TMOD: timer 1, mode 2, 8-bit reload      */
        TH1   = 0xFD;               /* TH1:reload value for 9600 baud @ 11.0592MHz   */
        TR1   = 1;                  /* TR1:timer 1 run                        */
        EA    = 1;                  /*打开总中断*/
        //ES    = 1;                  /*打开串口中断*///当使用串口协议通讯时可以使用此型号中断

}


void Uart_SendChar(unsigned chardat)
{
    SBUF = dat;
    while(!TI);
    TI = 0;
}

char putchar(char c)//重定向
{
    Uart_SendChar(c);
    return c;

}

/******************************************************************/
/*                  串口中断程序                                  */
/******************************************************************/


static unsigned char uart_temp = 0;          //定义临时变量
static unsigned char uart_cnt = 0;          //定义临时变量


void UART_isr(void) interrupt 4 //串行中断服务程序
{
        if(RI)                        //判断是接收中断产生
        {
                RI=0;                      //标志位清零
                uart_temp=SBUF;               //读入缓冲区的值
                if(uart_cnt==0)
                {
                        if(0x02 == uart_temp)
                        {
                                uart_cnt = 1;
                        }
                        else
                        {
                                uart_cnt = 0;
                        }
                }
                else if(uart_cnt==1)
                {
                        if(0x05 == uart_temp)
                        {
                                uart_cnt = 2;
                        }
                        else
                        {
                                uart_cnt = 0;
                        }
                }
                else if(uart_cnt==2)
                {
                        uart_cnt = 0;
                        //P1=uart_temp;                   //把值输出到P1口,用于观察
                        SBUF=uart_temp;               //把接收到的值再发回电脑端
                }
                else
                {
                        uart_cnt = 0;
                }
        }
        if(TI)                        //如果是发送标志位,清零
        {
                TI=0;
        }
}
//c51_uart.h文件
#ifndef __C51_UART_H__
#define __C51_UART_H__


extern void Uart_SendChar(unsigned chardat);
extern char putchar(char c);//重定向

extern void sys_uart_init(void);
extern void UART_isr(void);


#endif
//c51_lcd1602.c文件
#include "includes.h"

#include <string.h>

/******************************************************************/
/*                   写入命令函数                                 */
/******************************************************************/
void LCD_write_com(unsigned char com)
{
        RS_CLR;
        RW_CLR;
        EN_SET;
        P0 = com;
        delay_us(5);
        EN_CLR;
}

/******************************************************************/
/*                   写入数据函数                                 */
/******************************************************************/
void LCD_write_Data(unsigned char Data)
{
        RS_SET;
        RW_CLR;
        EN_SET;
        P0 = Data;
        delay_us(5);
        EN_CLR;
}


/****************************************
函数功能:LCD显示数字0-9
*****************************************/
void lcd_number(unsigned int number)
{
        int num={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};
        switch(number)
        {
                case 0:LCD_write_Data(num);
                break;
                case 1:LCD_write_Data(num);
                break;
                case 2:LCD_write_Data(num);
                break;
                case 3:LCD_write_Data(num);
                break;
                case 4:LCD_write_Data(num);
                break;
                case 5:LCD_write_Data(num);
                break;
                case 6:LCD_write_Data(num);
                break;
                case 7:LCD_write_Data(num);
                break;
                case 8:LCD_write_Data(num);
                break;
                case 9:LCD_write_Data(num);
                break;
        }
}

/******************************************************************/
/*                   初始化函数                                 */
/******************************************************************/
void LCD_init(void)
{
        LCD_write_com(0x38);    /*显示模式设置*/
        delay_ms(5);
        LCD_write_com(0x38);
        delay_ms(5);
        LCD_write_com(0x38);
        delay_ms(5);
        LCD_write_com(0x38);
        LCD_write_com(0x08);    /*显示关闭*/
        LCD_write_com(0x01);    /*显示清屏*/
        LCD_write_com(0x06);    /*显示光标移动设置*/
        delay_ms(5);
        LCD_write_com(0x0C);    /*显示开及光标设置*/
}



/******************************************************************/
/*                   写入字符串函数                              */
/*      X:第几列 Y:第几行*s字符串为空时跳出                      */
/******************************************************************/
void LCD_write_strl(unsigned char x,unsigned char y,unsigned char *s,unsigned length)
{   
        unsigned char cnt = 0;
        //LCD_write_com(0x01);    /*显示清屏*/
       
        if (y == 0)
        {   
                LCD_write_com(0x80 + x);   
        }
        else
        {   
                LCD_write_com(0xC0 + x);   
        }
      
        while(length--)
        {   
                LCD_write_Data( *s);   
                s ++;
                cnt++;
               
        }
}
//c51_lcd1602.h文件
#ifndef __C51_LCD1602_H__
#define __C51_LCD1602_H__



#include "STC89C5xRC_RDP.h"


//定义宏定义

sbit RS = P2^4;   //定义端口
sbit RW = P2^5;
sbit EN = P2^6;

#define RS_CLR RS=0
#define RS_SET RS=1
#define RW_CLR RW=0
#define RW_SET RW=1
#define EN_CLR EN=0
#define EN_SET EN=1


extern void LCD_write_com(unsigned char com) ;
extern void LCD_write_Data(unsigned char Data) ;
extern void lcd_number(unsigned int number);
extern void LCD_init(void) ;
extern void LCD_write_strl(unsigned char x,unsigned char y,unsigned char *s,unsigned length) ;




#endif
//c51_key.c文件
#include "includes.h"

sbit key1=P3^7;//定义按键位置 需要切换到独立按键模式
sbit key2=P3^6;
sbit key3=P3^5;
sbit key4=P3^4;
bit Flag = 0;
unsigned char key_num = 0;

/******************************************************************/
/*                  主函数                                    */
/******************************************************************/
unsigned char sys_key_single(void)
{
          if(!Flag)         //执行一次就停止了 先检测到的相应 复位后有效
      {
                  if(!key1)   {P1=0xFE;Flag=1;key_num=1;printf("The key_num :Number 1;\r\n");}//
                  else if(!key2){P1=0xFD;Flag=1;key_num=2;printf("The key_num :Number 2;\r\n");}//
                  else if(!key3){P1=0xFB;Flag=1;key_num=3;printf("The key_num :Number 3;\r\n");}//
                  else if(!key4){P1=0xF7;Flag=1;key_num=4;printf("The key_num :Number 4;\r\n");}//
                  else
                  {
                        key_num=0;
                  }
                  
                  
                //串口后台打印数字
      }
          return key_num;
}

//如果有干扰请加去抖程序
//红外接收头部分用黑色物质遮光,防止干扰按键
//c51_key.h文件
#ifndef __C51_KEY_H__
#define __C51_KEY_H__


extern unsigned char sys_key_single(void);//键盘扫描函数,使用行列反转扫描法

#endif
配套步伐
4 演示Proteus仿真

https://i-blog.csdnimg.cn/direct/57c8c2fcf1064f969b4ff6bc2cc380cb.png
5 总结

STC89C52R控制抢答器+数码管+背景表现+LCD1602x表现具有以下价值和上风:
1.
功能丰富性:整合抢答器、数码管、背景表现和LCD1602x表现功能,实现多样化的信息展示和控制功能。
2. 机动性:通过STC89C52R控制,系统具有机动的数据交换和控制能力,可根据需求定制表现内容和功能。
3. 用户体验:提供直观的数码表现和LCD1602x表现,加强用户交互体验,使信息更加清楚和易读。
4. 系统稳定性:采用STC89C52R作为控制核心,系统稳定可靠,包管长时间稳定运行。
5. 开发效率:整合多种表现功能和控制模块,简化开发流程,进步开发效率和系统集成度。
6. 教诲和培训:适用于教诲和培训范畴,帮助学习者理解嵌入式系统开发和控制原理。
7. 应用广泛:可用于各类竞赛、培训、演示等活动中,扩展了系统应用范畴和功能范围。
这些上风使得STC89C52R控制的抢答器与数码管、背景表现和LCD1602x表现系统成为一款具有实用性和创新性的嵌入式系统,可以或许满足多样化的需求并提拔用户体验。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 51单片机嵌入式开发:21、STC89C52R控制抢答器+数码管+背景表现+LCD1602x显