发作品签到
专业版

51单片机开发板

工程标签

63
0
0
0

简介

51单片机开发板,能够实现交通灯控制和温度检测和显示两个实验

简介:51单片机开发板,能够实现交通灯控制和温度检测和显示两个实验

开源协议

GPL 3.0

创建时间:2022-11-13 08:36:22更新时间:2025-01-06 03:27:06

描述

视频链接:

B站视频--功能演示及介绍
喜欢的话给up点点赞

项目简介

本项目是基于51单片机的开发板,用于完成单片机课程试验,能够用完成交通灯控制和温度检测和显示两个实验;通过添加拓展板可以实现基于温度控制的排风系统设计。

项目功能

此处可填写项目的相关功能及应用场景,示例:

本设计是基于STC89C51/52单片机设计的温湿度报警系统;设置有四个独立按键,功能分别为设置、加、减、确定,能实现报警阀值的调节,当温度或湿度超出阈值范围时,有报警提示声和对应的报警灯提示;

项目参数

此处可填写项目的相关功能参数介绍,示例:

  • 本设计采用STC89C52座位单片机;
  • 本设计采用LCD1602液晶显示,上行显示温度和工作模式,下行显示温度阈值设置。
  • 选用数字型温度传感器DS18B20,具有较宽的温度测量范围,可以满足一般需求;
  • 当温度在不同阈值范围时,LCD1602显示当前温度数值和风扇档位,风扇通过PWM调速实现不同转速

原理解析(硬件说明)

(1)、基于温度控制的排风系统包含两部分:
基于STC89C52的二合一实验板和万用板。基于STC89C52的二合一实验板包含STC89C52单片机最小系统、LCD1602显示模块、DS18B20温度传感器模块;万用板包含三个按键、风扇驱动电路。

image.png
图1 基于温度控制的排风系统示意图

(2)、Proteus仿真:
将程序编译为HEX文件导入Proteus仿真软件中,LCD1602显示的温度信息能随着DS180B20读数发生变化;模式能够根据当前温度和上下限阈值设置更改,风扇能根据模式调节转速。能够通过按键更改模式设置。
仿真结果一切正常。
在设计硬件电路之前,使用Proteus仿真软件测试硬件电路可行性以及代码运行效果。由于仿真软件得出结论与实际硬件电路会有所误差,软件仿真只能作为方案可行性分析的参考依据,需要在搭建好硬件框架后进行更加深入的调试。

image.png
图2 基于温度控制的排风系统Proteus仿真图

(3)、原理图设计部分:
在Proteus仿真软件成功完成验证方案可行性之后,使用嘉立创EDA软件完成原理图设计。
主要包括STC89C52最小系统、LCD1602显示模块、DS18B20温度传感器、三个独立按键、风扇驱动电路。
STC89C52最小系统:包括单片机、排针引出、晶振电路、上电复位和按键复位、TYPE-C供电接口、P0口上拉电阻、供电指示灯、串口下载指示灯、程序下载接口、滤波电容,预留了四组对外供电接口;
LCD1602显示模块驱动电路:V0口用于控制显示模块对比度,A和K为背光正负极,D0-D7为8位双向数据总线,RS为数据、命令寄存器选择段,RW为读/写选择端,EN为使能端。
DS18B20温度传感器的DQ口为数据I/O总线,使用时需要一个弱上拉电阻(4.7k左右)。
三个独立按键连接单片机IO口作为输入。
风扇驱动电路1为直接耦合型二级放大电路,当S8050三极管基极输入高电平时,三极管导通,S8050集电极电位被拉低,此时满足S8550导通条件,成功驱动风扇。两级放大电路增大输出电流,提高驱动能力,性能较强。
由于缺乏S8550元件,设计了风扇驱动电路2优点是电路较为简单,缺点是带负载能力不足。快恢复二极管:续流作用,电动机是感性原件,感性元件的电流不能突变,当电动机停止供电的时候,二极管给感性元件一个回流的通路。电容:滤波作用,防止直流电机转动时,换向片之间一些高频干扰信号,为了防止这种干扰通过电机电源线串入供电电路,影响与电机共用一组电源的其它电路的正常工作。
风扇接口用于连接风扇。

image.png
图3 STC89C52最小系统原理图

image.png
图4 LCD1602显示模块和DS18B20温度传感器原理图

image.png
图5 万用板原理图(三个独立按键、风扇驱动电路、风扇接口)

(4)、PCB设计部分:
STC89C52实验板包含STC89C52最小系统、LCD1602显示模块、DS18B20温度传感器、5V供电输出接口。万用板包含三个独立按键、风扇驱动电路、风扇接口、风扇固定位置,由于万用板面积较大,以模块化的方式设计,将其与单片机引出排针连接后便可使用。
布局方面:上方为LCD1602显示模块,左下方为STC89C52最小系统,右侧为DS18B20温度传感器,通过优化布线将元器件全部设计在正面,方便焊接和测试。
走线方面:电源线均采用加粗处理,信号线拐角处均做了圆弧化处理,线路与焊盘连接处均添加泪滴,提高了硬件设计的可靠性。
交互方面:输入接口设计在左侧和下方,输出接口设计在右侧,按键尽可能设计位于右下方,显示模块设计在上方。于市场上大部分成熟产品相符合,符合使用习惯,在烧录程序、调整参数、观察实验结果等场景下较为方便。
image.png

image.png

软件代码

(1)、主函数流程图:
在循环前转换一次温度可以防止LCD1602显示85℃的错误。
image.png
(2)、软件结构
采用了库函数的方式,函数高度复用,方便了程序编写和调试过程。

image.png
(3)、部分函数分析:(此处仅对函数做分析,代码内容为了方便观看做了优化,完整代码见附录)
1)主函数:
由于DS18B20暂存器中存有一个85℃的数值,在LCD1602显示和温度参与风扇调速之前需要经过一次转换,避免将85℃在LCD1602上显示出来或者对风扇转速造成影响。
对于屏幕上固定的文本信息如“TH”、“TL”“T”、“MOD”等,在循环之前显示出来避免在循环过程中不断刷新屏幕导致性能浪费。
在温度上下限阈值部分添加越位检测功能。上限不能低于下限、上限不能高于125℃、下线不能低于-55℃。
在程序中使用“flag %= 3;”这样的写法将flag的数值限制为0、1、2三个数值,三个数值分别表示退出设置功能、设置温度上限和设置温度下限。此种写法相较于使用if语句判断后置为0的方法减小了对单片机性能的占用。类似的写法还有“Counter %= 100;”,Counter为输出PWM时的计数值,被限制在0~99范围内。
人机交互方面的优化,使用LCD1602字模表中的“0x7E”和“0x7F”分别为右箭头和左箭头,在设置温度上下限时,使用左箭头和右箭头对当前修改信息进行提示,如图13所示。
image.png

  1. #include
  2. #include "LCD1602.h"
  3. #include "DS18B20.h"
  4. #include "Delay.h"
  5. #include "Key.h"
  6. #include "Timer.h"
  7. float T, TShow;
  8. char TLow, THigh;
  9. unsigned char KeyNum;
  10. unsigned char Counter, Compare;
  11. unsigned char flag = 0;
  12. sbit Motor = P3 ^ 3;
  13. void main()
  14. {
  15. Motor = 1;  
    
  16. DS18B20_ConvertT(); //上电先转换一次温度,防止第一次读数据错误  
    
  17. Delay(500);         //等待转换完成  
    
  18. THigh = 35;  
    
  19. TLow  = 10;  
    
  20. LCD_Init();  
    
  21. LCD_ShowString(1, 1, "T:");  
    
  22. LCD_ShowChar(1, 7, '.'); //显示小数点  
    
  23. LCD_ShowString(2, 1, "TH:");  
    
  24. LCD_ShowString(2, 10, "TL:");  
    
  25. LCD_ShowString(1, 12, "MOD:");  
    
  26. LCD_ShowSignedNum(2, 4, THigh, 3);  
    
  27. LCD_ShowSignedNum(2, 13, TLow, 3);  
    
  28. TimerInit();  
    
  29. while (1) {  
    
  30.     KeyNum = Key();  
    
  31.     /*温度读取及显示*/  
    
  32.     DS18B20_ConvertT();  //转换温度  
    
  33.     T = DS18B20_ReadT(); //读取温度  
    
  34.     if (T < 0)           //如果温度小于0  
    
  35.     {  
    
  36.         LCD_ShowChar(1, 3, '-'); //显示负号  
    
  37.         TShow = -T;              //将温度变为正数  
    
  38.     } else                       //如果温度大于等于0  
    
  39.     {  
    
  40.         LCD_ShowChar(1, 3, '+'); //显示正号  
    
  41.         TShow = T;  
    
  42.     }  
    
  43.     LCD_ShowNum(1, 4, TShow, 3);                              //显示温度整数部分  
    
  44.     LCD_ShowNum(1, 8, (unsigned long)(TShow * 100) % 100, 2); //显示温度小数部分  
    
  45.     /*阈值判断及显示*/  
    
  46.     if (KeyNum) {  
    
  47.         if (KeyNum == 1) // K1按键,改变flag  
    
  48.         {  
    
  49.             flag++;  
    
  50.         }  
    
  51.         if (flag == 0)  
    
  52.             ;  
    
  53.         {  
    
  54.             LCD_ShowChar(2, 9, 0x20);  
    
  55.         }  
    
  56.         if (flag == 1) {  
    
  57.             LCD_ShowChar(2, 8, 0x7F);  
    
  58.             if (KeyNum == 2) // K2按键,THigh自增  
    
  59.             {  
    
  60.                 THigh++;  
    
  61.                 if (THigh > 125) { THigh = 125; }  
    
  62.             }  
    
  63.             if (KeyNum == 3) // K3按键,THigh自减  
    
  64.             {  
    
  65.                 THigh--;  
    
  66.                 if (THigh <= TLow) { THigh++; }  
    
  67.             }  
    
  68.         }  
    
  69.         if (flag == 2) {  
    
  70.             LCD_ShowChar(2, 8, 0x20);  
    
  71.             LCD_ShowChar(2, 9, 0x7E);  
    
  72.             if (KeyNum == 2) // K2按键,THigh自减  
    
  73.             {  
    
  74.                 TLow++;  
    
  75.                 if (TLow >= THigh) { TLow--; }  
    
  76.             }  
    
  77.             if (KeyNum == 3) // K3按键,TLow自增  
    
  78.             {  
    
  79.                 TLow--;  
    
  80.                 if (TLow < -55) { TLow = -55; }  
    
  81.             }  
    
  82.         }  
    
  83.         flag %= 3;  
    
  84.         LCD_ShowSignedNum(2, 4, THigh, 3); //显示阈值数据  
    
  85.         LCD_ShowSignedNum(2, 13, TLow, 3);  
    
  86.     }  
    
  87.     if (T > THigh) //越界判断  
    
  88.     {  
    
  89.            LCD_ShowNum(1, 16, 3, 1);  
    
  90.            Compare = 100;  
    
  91.        } else if (T < TLow) {  
    
  92.            LCD_ShowNum(1, 16, 1, 1);  
    
  93.            Compare = 63;  
    
  94.        } else {  
    
  95.            LCD_ShowNum(1, 16, 2, 1);  
    
  96.            Compare = 75;  
    
  97.        }  
    
  98.        Key_Loop(); //每20ms调用一次按键驱动函数  
    
  99.    }  
    
  100. }
  101. /电机PWN/
  102. void Timer0_Routine() interrupt 1
  103. {
  104.    // 300uS  
    
  105.    TL0 = 0xD3; //设置定时初值  
    
  106.    TH0 = 0xFE; //设置定时初值  
    
  107.    Counter++;  
    
  108.    Counter %= 100;        //计数值变化范围限制在0~99  
    
  109.    if (Counter < Compare) //计数值小于比较值  
    
  110.    {  
    
  111.        Motor = 1; //输出1  
    
  112.    } else         //计数值大于比较值  
    
  113.    {  
    
  114.        Motor = 0; //输出0  
    
  115.    }  
    
  116. }

2)按键库:
Key_GetState函数:通过判断按下的按键,分别将KeyNumber赋值为1,2,3。

  1. unsigned char Key_GetState()
  2. {
  3.  unsigned char KeyNumber=0;  
    
  4.  if(P3_5==0){KeyNumber=1;}  
    
  5.  if(P3_6==0){KeyNumber=2;}  
    
  6.  if(P3_7==0){KeyNumber=3;}  
    
  7.  return KeyNumber;  
    
  8. }

Key函数:将三个按键分别编码为1、2、3,没有按下的状态均编码为0。方便后续进行判断。

  1. unsigned char Key(void)
  2. {
  3.  unsigned char Temp=0;  
    
  4.  Temp=Key_KeyNumber;  
    
  5.  Key_KeyNumber=0;  
    
  6.  return Temp;  
    
  7. }

Key_Loop函数:通过现态和次态对比的方式进行下降沿检测按键,将此函数放在主函数的循环中可以方便地完成按键检测。

  1. void Key_Loop(void)
  2. {
  3.  static unsigned char NowState,LastState;  
    
  4.  LastState=NowState;             //按键状态更新  
    
  5.  NowState=Key_GetState();        //获取当前按键状态  
    
  6.  //如果上个时间点按键按下,这个时间点未按下,则是松手瞬间,以此避免消抖和松手检测  
    
  7.  if(LastState==1 && NowState==0)  
    
  8.  {  
    
  9.      Key_KeyNumber=1;  
    
  10. }  
    
  11. if(LastState==2 && NowState==0)  
    
  12. {  
    
  13.     Key_KeyNumber=2;  
    
  14. }  
    
  15. if(LastState==3 && NowState==0)  
    
  16. {  
    
  17.     Key_KeyNumber=3;  
    
  18. }  
    
  19. }

3)单总线库OneWire.c
DS18B20单总线许多操作对时序要求较为严格,为了避免PWM定时器中断影响DS18B20时序从而导致温度读取异常,此库中设计时序的部分均先将EA关闭,在操作完成后将EA开启。使用EA控制定时器关闭而不是TR0的原因是在EA=0的时间内如果发生中断,会在EA=1之后立即进入中断;而使用TR0的方式会导致此次中断被跳过。
OneWire_Init函数:如图14所示,单总线通信在每一次操作之前需要使用下列代码生成一个初始化信号,即拉低480微秒,之后需要经过一个Resistor pullup才可以进行下一个操作。

image.png

  1. unsigned char OneWire_Init(void)
  2. {
  3.  unsigned char i;  
    
  4.  unsigned char AckBit;  
    
  5.  EA=0;  
    
  6.  OneWire_DQ=1;  
    
  7.  OneWire_DQ=0;  
    
  8.  i = 246;while (--i);        //Delay 500us  
    
  9.  OneWire_DQ=1;  
    
  10. i = 32;while (--i);         //Delay 70us  
    
  11. AckBit=OneWire_DQ;  
    
  12. i = 246;while (--i);        //Delay 500us  
    
  13. EA=1;  
    
  14. return AckBit;  
    
  15. }
    OneWire_SendBit函数:一次只能够从单总线上发送一个位。如图15所示:主机将总线拉低60-120us,然后释放总线,表示发送0;主机将总线拉低1-15us,然后释放总线,表示发送1。从机将在总线拉低30us后(典型值)读取电平,整个时间片应大于60us。

image.png

  1. void OneWire_SendBit(unsigned char Bit)
  2. {
  3.  unsigned char i;  
    
  4.  EA=0;  
    
  5.  OneWire_DQ=0;  
    
  6.  i = 3;while (--i);          //Delay 10us  
    
  7.  OneWire_DQ=Bit;  
    
  8.  i = 24;while (--i);         //Delay 50us  
    
  9.  OneWire_DQ=1;  
    
  10. EA=1;  
    
  11. }

OneWire_SendByte函数:一次只能够从单总线上发送一个位,想要发送一字节数据只需需要连续发送八次即可。

  1. void OneWire_SendByte(unsigned char Byte)
  2. {
  3.  unsigned char i;  
    
  4.  for(i=0;i<8;i++)  
    
  5.  {  
    
  6.      OneWire_SendBit(Byte&(0x01<
    

#include "LCD1602.h"
#include "DS18B20.h"
#include "Delay.h"
#include "Key.h"
#include "Timer.h"

float T, TShow;
char TLow, THigh;
unsigned char KeyNum;
unsigned char Counter, Compare;
unsigned char flag = 0;
sbit Motor = P3 ^ 3;

void main()
{
Motor = 1;
DS18B20_ConvertT(); //上电先转换一次温度,防止第一次读数据错误
// Delay(500); //等待转换完成

THigh = 35;
TLow = 10;

LCD_Init();

LCD_ShowString(1, 1, "T:");
LCD_ShowChar(1, 7, '.'); //显示小数点
LCD_ShowString(2, 1, "TH:");
LCD_ShowString(2, 10, "TL:");
LCD_ShowString(1, 12, "MOD:");
LCD_ShowSignedNum(2, 4, THigh, 3);
LCD_ShowSignedNum(2, 13, TLow, 3);

TimerInit();

while (1) {
KeyNum = Key();

/*温度读取及显示*/
DS18B20_ConvertT();  //转换温度
T = DS18B20_ReadT(); //读取温度
if (T < 0)      //如果温度小于0
{
  LCD_ShowChar(1, 3, '-'); //显示负号
  TShow = -T;        //将温度变为正数
} else            //如果温度大于等于0
{
  LCD_ShowChar(1, 3, '+'); //显示正号
  TShow = T;
}
LCD_ShowNum(1, 4, TShow, 3);                //显示温度整数部分
LCD_ShowNum(1, 8, (unsigned long)(TShow * 100) % 100, 2); //显示温度小数部分

/*阈值判断及显示*/
if (KeyNum) {
  if (KeyNum == 1) // K1按键,改变flag
  {
    flag++;
  }
  if (flag == 0)
    ;
  {
    LCD_ShowChar(2, 9, 0x20);
  }

  if (flag == 1) {
    LCD_ShowChar(2, 8, 0x7F);
    if (KeyNum == 2) // K2按键,THigh自增
    {
      THigh++;
      if (THigh > 125) { THigh = 125; }
    }
    if (KeyNum == 3) // K3按键,THigh自减
    {
      THigh--;
      if (THigh <= TLow) { THigh++; }
    }
  }
  if (flag == 2) {
    LCD_ShowChar(2, 8, 0x20);
    LCD_ShowChar(2, 9, 0x7E);
    if (KeyNum == 2) // K2按键,THigh自减
    {
      TLow++;
      if (TLow >= THigh) { TLow--; }
    }
    if (KeyNum == 3) // K3按键,TLow自增
    {
      TLow--;
      if (TLow < -55) { TLow = -55; }
    }
  }
  flag %= 3;

  LCD_ShowSignedNum(2, 4, THigh, 3); //显示阈值数据
  LCD_ShowSignedNum(2, 13, TLow, 3);
}
if (T > THigh) //越界判断
{
  LCD_ShowNum(1, 16, 3, 1);
  Compare = 100;
} else if (T < TLow) {
  LCD_ShowNum(1, 16, 1, 1);
  Compare = 63;
} else {
  LCD_ShowNum(1, 16, 2, 1);
  Compare = 75;
}
Key_Loop(); //每20ms调用一次按键驱动函数

}
}
/电机PWN/
void Timer0_Routine() interrupt 1
{
// 300uS
TL0 = 0xD3; //设置定时初值
TH0 = 0xFE; //设置定时初值
Counter++;
Counter %= 100; //计数值变化范围限制在0~99
if (Counter < Compare) //计数值小于比较值
{
Motor = 1; //输出1
} else //计数值大于比较值
{
Motor = 0; //输出0
}
}

2.单总线库:OneWire.c
#include

//引脚定义
sbit OneWire_DQ=P1^0;

unsigned char OneWire_Init(void)
{
unsigned char i;
unsigned char AckBit;
EA=0;
OneWire_DQ=1;
OneWire_DQ=0;
i = 246;while (--i); //Delay 500us
OneWire_DQ=1;
i = 32;while (--i); //Delay 70us
AckBit=OneWire_DQ;
i = 246;while (--i); //Delay 500us
EA=1;
return AckBit;
}

void OneWire_SendBit(unsigned char Bit)
{
unsigned char i;
EA=0;
OneWire_DQ=0;
i = 3;while (--i); //Delay 10us
OneWire_DQ=Bit;
i = 24;while (--i); //Delay 50us
OneWire_DQ=1;
EA=1;
}

unsigned char OneWire_ReceiveBit(void)
{
unsigned char i;
unsigned char Bit;
EA=0;
OneWire_DQ=0;
i = 2;while (--i); //Delay 5us
OneWire_DQ=1;
i = 2;while (--i); //Delay 5us
Bit=OneWire_DQ;
i = 24;while (--i); //Delay 50us
EA=1;
return Bit;
}

void OneWire_SendByte(unsigned char Byte)
{
unsigned char i;
for(i=0;i<8;i++)
{
OneWire_SendBit(Byte&(0x01<
#include "OneWire.h"

//DS18B20指令
#define DS18B20_SKIP_ROM 0xCC
#define DS18B20_CONVERT_T 0x44
#define DS18B20_READ_SCRATCHPAD 0xBE

void DS18B20_ConvertT(void)
{
OneWire_Init();
OneWire_SendByte(DS18B20_SKIP_ROM);
OneWire_SendByte(DS18B20_CONVERT_T);
}

float DS18B20_ReadT(void)
{
unsigned char TLSB,TMSB;
int Temp;
float T;
OneWire_Init();
OneWire_SendByte(DS18B20_SKIP_ROM);
OneWire_SendByte(DS18B20_READ_SCRATCHPAD);
TLSB=OneWire_ReceiveByte();
TMSB=OneWire_ReceiveByte();
Temp=(TMSB<<8)|TLSB;
T=Temp/16.0;
return T;
}

DS18B20头文件:DS18B20.h
#ifndef DS18B20_H
#define DS18B20_H
void DS18B20_ConvertT(void);
float DS18B20_ReadT(void);
#endif

4.按键库:Key.c
#include
#include "Delay.h"

unsigned char Key_KeyNumber;

unsigned char Key(void)
{
unsigned char Temp=0;
Temp=Key_KeyNumber;
Key_KeyNumber=0;
return Temp;
}

unsigned char Key_GetState()
{
unsigned char KeyNumber=0;

if(P3_5==0){KeyNumber=1;}
if(P3_6==0){KeyNumber=2;}
if(P3_7==0){KeyNumber=3;}

return KeyNumber;
}

void Key_Loop(void)
{
static unsigned char NowState,LastState;
LastState=NowState; //按键状态更新
NowState=Key_GetState(); //获取当前按键状态
//如果上个时间点按键按下,这个时间点未按下,则是松手瞬间,以此避免消抖和松手检测
if(LastState==1 && NowState==0)
{
Key_KeyNumber=1;
}
if(LastState==2 && NowState==0)
{
Key_KeyNumber=2;
}
if(LastState==3 && NowState==0)
{
Key_KeyNumber=3;
}
}

按键头文件:Key.h
#ifndef KEY_H
#define KEY_H
unsigned char Key(void);
void Key_Loop(void);
#endif

5.LCD1602库:LCD1602.c
#include

//引脚配置:
sbit LCD_RS=P1^7;
sbit LCD_RW=P1^6;
sbit LCD_EN=P1^5;
#define LCD_DataPort P2

void LCD_Delay()
{
unsigned char i, j;

i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}

void LCD_WriteCommand(unsigned char Command)
{
LCD_RS=0;
LCD_RW=0;
LCD_DataPort=Command;
LCD_EN=1;
LCD_Delay();
LCD_EN=0;
LCD_Delay();
}

void LCD_WriteData(unsigned char Data)
{
LCD_RS=1;
LCD_RW=0;
LCD_DataPort=Data;
LCD_EN=1;
LCD_Delay();
LCD_EN=0;
LCD_Delay();
}

void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
if(Line==1)
{
LCD_WriteCommand(0x80|(Column-1));
}
else if(Line==2)
{
LCD_WriteCommand(0x80|(Column-1+0x40));
}
}

void LCD_Init()
{
LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵
LCD_WriteCommand(0x0C);//显示开,光标关,闪烁关
LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动
LCD_WriteCommand(0x01);//光标复位,清屏
}

void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{
LCD_SetCursor(Line,Column);
LCD_WriteData(Char);
}

void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
{
unsigned char i;
LCD_SetCursor(Line,Column);
for(i=0;String[i]!='\0';i++)
{
LCD_WriteData(String[i]);
}
}

int LCD_Pow(int X,int Y)
{
unsigned char i;
int Result=1;
for(i=0;i0;i--)
{
LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
}
}

void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
{
unsigned char i;
unsigned int Number1;
LCD_SetCursor(Line,Column);
if(Number>=0)
{
LCD_WriteData('+');
Number1=Number;
}
else
{
LCD_WriteData('-');
Number1=-Number;
}
for(i=Length;i>0;i--)
{
LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');
}
}

void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i,SingleNumber;
LCD_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
SingleNumber=Number/LCD_Pow(16,i-1)%16;
if(SingleNumber<10)
{
LCD_WriteData(SingleNumber+'0');
}
else
{
LCD_WriteData(SingleNumber-10+'A');
}
}
}

void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i;
LCD_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');
}
}

LCD1602头文件;LCD1602.h
#ifndef LCD1602_H
#define LCD1602_H

//用户调用函数:
void LCD_Init();
void LCD_WriteCommand(unsigned char Command);
void LCD_WriteData(unsigned char Data);
void LCD_SetCursor(unsigned char Line, unsigned char Column);
void LCD_ShowChar(unsigned char Line, unsigned char Column, char Char);
void LCD_ShowString(unsigned char Line, unsigned char Column, char *String);
void LCD_ShowNum(unsigned char Line, unsigned char Column, unsigned int Number, unsigned char Length);
void LCD_ShowSignedNum(unsigned char Line, unsigned char Column, int Number, unsigned char Length);
void LCD_ShowHexNum(unsigned char Line, unsigned char Column, unsigned int Number, unsigned char Length);
void LCD_ShowBinNum(unsigned char Line, unsigned char Column, unsigned int Number, unsigned char Length);

#endif

6.延时函数:Delay.c
void Delay(unsigned int xms)
{
unsigned char i, j;
while(xms--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}

延时函数头文件:Delay.h
#ifndef DELAY_H
#define DELAY_H
void Delay(unsigned int xms);
#endif

  1. 定时器初始化库:Timer.c
    #include

void TimerInit(void)
{
TMOD = 0x10;
TL0 = 0xD3; //设置定时初值
TH0 = 0xFE; //设置定时初值
TF0 = 0;
TR0 = 1;
ET0 = 1;
EA = 1;
}

定时器库:Timer.h
#ifndef TIMER_H
#define TIMER_H
void TimerInit(void);
#endif

设计图

未生成预览图,请在编辑器重新保存一次

BOM

暂无BOM

附件

序号文件名称下载次数
暂无数据
克隆工程
添加到专辑
0
0
分享
侵权投诉

评论

全部评论(1)
按时间排序|按热度排序
粉丝0|获赞0
相关工程
暂无相关工程

底部导航