EDN首页   博客首页

最新日志

发表于:2008-11-18 17:39:25
标签:C8051F020  

7

超声波测距器的设计

                             超声波测距器的设计

 

 

超声波测距器在汽车倒车,建筑工地和一些工业现场有着很广泛的用途。其测量范围0.10~4.0 m,测量精度可高达1 cm左右。

                                                1.1

本设计采用新型8051控制器c8051f020,系统采用22.1184MHZ的高精度晶振,来获得稳定的时间频率,以减少测量误差。C8051f020P3.0端口输出超声波换能器所需的40khz方波信号,利用中断口检测超声波接收电路输出的返回信号。显示电路采用SPI延伸的LCD1602液晶。

 

本设计的重点就是超声波的接收和发射电路。

超声波的发射电路如下图1.2

点击看大图

                          图1.2

发射电路主要由反向器74HC04和超声波换能器构成,P3.0端口输出的40khz方波信号一路经反向器送到超声波换能器的一个电极,另一路经两级反向器后送到超声波换能器的另一个电极,用这种方式可以提高超声波的发射强度。

超声波接收电路如下图1.3

点击看大图

                                            1.3

集成电路CX20106A是一款红外接收的专用芯片,常用于电视红外遥控器。常用的载波频率38khz与测距的40khz较为相近,可以利用它来做接收电路。适当的改变C3的大小,可以改变接受电路的灵敏度和抗干扰能力。

显示电路如下图1.4

                                               1.4

采用c8051f020 SPI 从而驱动595控制lcd1602. 其中LCDCS595的片选信号

本设计把片选信号 定义为P3.1 .

sbit   LCDCS  P3^1;

 

另一个重点就是超声波测距的算法计算。

D =  S/2(v+t)/2     ---------------------------------------------------------------------------1-1

其中D为被测物与测距器的距离。

    S为声波的来回路程。

    V为声速。

    T为所用时间。

 

C8051F020 外设及其丰富,本设计只用到了外部中断和SPI的部分管脚,在此基础上还可以增加不少内容,纯粹使用前后台系统,会使系统的适时性受到限制,在下篇我会详细介绍基于c8051f020的ucos_II的移植。

代码部分:

 

//-------------------------------------------------------------------------

//  SPI_Init()

//-------------------------------------------------------------------------

void SPI0_Init (void)

{

   SPI0CFG = 0x07;                     // data sampled on 1st SCK rising edge

                                       // 8-bit data words

   SPI0CFG|=0x40;                      //CKPOL =1;01000111

 

   SPI0CN = 0x03;                      // Master mode; SPI enabled; flags

                                       // cleared

   SPI0CKR = SYSCLK/2/2000000-1;       // SPI clock <= 8MHz (limited by

                                       // EEPROM spec.)

}

 

void MSPI_SendData(unsigned char  ddata)

{ 

    LCDCS = 0;                      // 片选HC595

     SPIF = 0;

     SPI0DAT = ddata;

     while (SPIF == 0);                   // 等待写结束

    LCDCS = 1;

}

 

 

                        ----------------------------------zjw5000   2008-11-18 

系统分类: 单片机   |    用户分类:    |    来源: 原创

该用户于2008-11-19 0:46:43编辑过该文章

评论(2) | 阅读(661)
发表于:2008-11-18 1:19:00
标签:c8051f020  

3

c8051f020系列学习-----SPI篇

硬件简介: 

          C8051F020器件是完全集成的混合信号系统级MCU芯片(SOC),它使用Cygnal的专利CIP-51微控制器内核,CIP-51与MCS-51指令集完全兼容。它采用流水线结构,与标准的8051结构相比指令执行速度有很大的提高。CIP-51提供了22个中断源,允许大量的模拟和数字外设中断微控制器,因而有更高的执行效率。具有64个I/O引脚,每个端口都可以配置成推挽或漏极开路输出。C8051F020 MCU内部有一个SMBUS/I2C接口、两个具有增强型波特率配置的全双工UART和一个增强型SPI接口,每种串行总线完全用硬件实现,都能向CIP-51产生中断。它内部有一个12位的ADC0,该子系统包括一个9 通道的可编程模拟多路选择器(AMUX0),一个可编程增益放大器(PGA0)和一个100ksps、12 位分辨率的逐次逼近寄存器型ADC,ADC中集成了跟踪保持电路和可编程窗口检测器;一个8位的ADC1,包括一个8 通道的可配置模拟多路开关(AMUX1),一个可编程增益放大器(PGA1)和一个500ksps、8 位分辨率的逐次逼近寄存器型ADC。两个12位的DAC转换器,每个DAC 都具有灵活的输出更新机制,允许无缝的满度变化并支持无抖动输出更新。C8051F020还有5个通用的16位定时器和5 个捕捉/比较模块的可编程计数器/定时器阵列。

        设置交叉开关表将P0.2、P0.3和P0.4引脚配置为SPI接口, 其主要函数:

void SendSPIByte(unsigned char ch)  // 通过SPI发送一个字节数据

{

         SPIF = 0;                   // SPIF位清零

         SPI0DAT = ch;              // 启动一次数据发送

         while (SPIF == 0);                // 等待数据发送完毕

}

unsigned char GetSPIByte(void)    //通过SPI接收一个字节数据

{

    SPIF = 0;                  // SPIF位清零

         SPI0DAT = 0;              //启动一次数据接收

         while (SPIF == 0);          // 等待数据接收完毕

         return  SPI0DAT;          // 读取SPI接收到的数据

}

 

系统分类: 单片机   |    用户分类:    |    来源: 原创

该用户于2008-11-18 14:59:16编辑过该文章

评论(0) | 阅读(332)
发表于:2008-10-29 19:56:07
标签:C8051F020  

3

c8051f020 ds1302

         C8051F020片内含CIP-51的CPU内核,它的指令系统与MCS-51完全兼容。

         其中的C8051F020单片机含有64kB片内Flash程序存储器,4352B的RAM、8个I/O端口共64根I/O口线、一个12位A/D转换器和一个8位A/D转换器以及一个双12位D/A转换器、2个比较器、5个16位通用定时器、5个捕捉/比较模块的可编程计数/定时器阵列、看门狗定时器、VDD监视器和温度传感部分.

     所以c51的程序很容易拿到c8051f来。基本不用修改。

源码:

/*******************************************************************

 DS1302

********************************************************************/
#include "c8051f020.h" 
#include "stdio.h"
 
#define uchar unsigned char
long result;

#define BAUDRATE     19200            // Baud rate of UART in bps
#define SYSCLK       22118400          // SYSCLK frequency in Hz

sbit SCLK = P3^4;
sbit IO   = P3^3;
sbit RSTB = P3^5;

/**************************** 函数原型说明 ****************************/
uchar rbyte_3w();    // 字节读取函数
void reset_3w();    // 复位函数
void wbyte_3w(uchar);   // 字节写入函数
void initialize_DS1302(); // DS1302初始化函数
void disp_clk_regs(uchar); // 显示时钟寄存器内容函数

/*******************SYSCLK_Init函数*************************************/

void SYSCLK_Init (void)
{
   int i;                              /*延时计数器*/

   OSCXCN = 0x67;                      /*打开外部晶体振荡器*/
   for (i=0; i < 256; i++) ;           /*延时*/

   while (!(OSCXCN & 0x80)) ;          /*查询外部晶体是否稳定起振*/

   OSCICN = 0x88;                      /*用外部晶体作为系统时钟,并使能时钟丢失检测*/
}
/***************************UART0_Init函数***************************/
void UART0_Init (void)
{
   SCON0   = 0x50;                     /*SCON0:模式1,8位UART,时能RX*/
   TMOD    = 0x20;                     /*TMOD: 定时器工作再模式2, 8位重载*/
   TH1    = -(SYSCLK/BAUDRATE/16);     /*设置定时1用作波特率的重载值*/
   TR1    = 1;                         /*开定时器1*/
   CKCON |= 0x10;                      /*定时器1用系统时钟作为它的时基*/
   PCON  |= 0x80;                      /*SMOD00 = 1*/
}
/****************************PORT_Init函数**************************/
void PORT_Init (void)
{
   XBR0    = 0x04;                     /*使能UART0*/
   XBR1    = 0x00;
   XBR2    = 0x40;                     /*使能交叉开关和弱上拉*/
   P0MDOUT |= 0x01;                    /*使能TX0作为推挽输出*/
   P1MDOUT |= 0x40;                    /*时能P1.6 (LED)作为推挽输出*/
   P3MDOUT |= 0xff;
}
/***************************** 复位函数 ******************************/
void reset_3w() {
   SCLK = 0;
   RSTB = 0;
   RSTB = 1;
}

/****************************** 字节写入函数 ***************************/
void wbyte_3w(uchar W_Byte) {
uchar i;
 for(i = 0; i < 8; ++i) {
  IO = 0;
  if(W_Byte & 0x01) IO = 1;
  SCLK = 0;
  SCLK = 1;
  W_Byte >>= 1;
    }
}

/****************************** 字节读取函数 ****************************/
uchar rbyte_3w() {
uchar i;
uchar R_Byte;
uchar TmpByte;

 R_Byte = 0x00;
 IO = 1;
 for(i=0; i<8; ++i) {
  SCLK = 1;
  SCLK = 0;
  TmpByte = (uchar)IO;
  TmpByte <<= 7;
  R_Byte >>= 1;
  R_Byte |= TmpByte;
 }
 return R_Byte;
}
/************************* 显示时钟寄存器内容函数 ***********************/
void disp_clk_regs(uchar loop) {
uchar lsec = 99, sec, min, hrs, dte, mon, day, yr;

do {     // 读取并显示时钟寄存器的内容
  reset_3w();
  wbyte_3w(0xBF);  // 以多字节突发方式读取时钟数据
  sec = rbyte_3w(); // 秒
  min = rbyte_3w(); // 分
  hrs = rbyte_3w(); // 小时
  dte = rbyte_3w(); // 日期
  mon = rbyte_3w(); // 月份
  day = rbyte_3w(); // 星期
  yr  = rbyte_3w(); // 年
  reset_3w();
  if(sec != lsec || !loop) { // 每秒显示一次  
   printf("\nYr   Day  Mon  Dte  Hrs  Min  Sec");
   printf("\n%2.bX   %2.bX   %2.bX   %2.bX", yr, day, mon, dte);
   printf("   %2.bX   %2.bX   %2.bX", hrs, min, sec);
   lsec = sec;
 }
 while(1); 
}
/**************************** DS1302初始化函数 **************************/
void initialize_DS1302() {
uchar yr, mn, date, dy, hr, min, sec;

 printf("\nEnter the year (0-99): ");
 scanf("%bx", &yr);
 printf("\nEnter the month (1-12): ");
 scanf("%bx", &mn);
 printf("\nEnter the date (1-31): ");
 scanf("%bx", &date);
 printf("\nEnter the day (1-7): ");
 scanf("%bx", &dy);
 printf("\nEnter the hour (1-24): ");
 scanf("%bx", &hr);
 hr = hr & 0x3f;    // 设置时钟为24小时方式
 printf("\nEnter the minute (0-59): ");
 scanf("%bx", &min);
 printf("\nEnter the second (0-59): ");
 scanf("%bx", &sec);

 reset_3w();
 wbyte_3w(0x8e);    // 写保护控制寄存器
 wbyte_3w(0);    // 允许写入
 reset_3w();
 wbyte_3w(0x90);    // 涓流充电控制寄存器
 wbyte_3w(0xab);    // 允许充电, 双二极管, 8K 电阻
 reset_3w();
 wbyte_3w(0xbe);    // 以多字节突发方式写入时钟数据(8个字节)
 wbyte_3w(sec);
 wbyte_3w(min);
 wbyte_3w(hr);
 wbyte_3w(date);
 wbyte_3w(mn);
 wbyte_3w(dy);
 wbyte_3w(yr);
 wbyte_3w(0);    // 以多字节突发方式写入时钟数据时
                                // 必须对写保护控制寄存器写入0值
 reset_3w();
}

/****************************** 主函数 *********************************/
main (void) 

    WDTCN = 0xde;                       /*关看门狗*/
    WDTCN = 0xad;

    SYSCLK_Init ();                     /*初始化系统时钟*/
    PORT_Init ();                       /*初始挂交叉开关和I/O口*/
    UART0_Init ();                      /*初始化UART0*/       
 while (1) {  
 printf("\r***********C51 PROGRAM FOR DS1302***********\n\n");
 printf("I. initialize DS1302\n");
 printf("CW. Write Byte  CR. Read Time\n");
 printf("RW. Write RAM   RR. Read RAM\n");
 printf("\nEnter Menu Selection:");
 initialize_DS1302();
 disp_clk_regs(1);
 }
}

 

运行结果:

 

 

 



   

 

系统分类: 单片机   |    用户分类:    |    来源: 原创

评论(0) | 阅读(129)
发表于:2008-10-27 16:58:11
标签:C8051F  

9

基于DDS技术的数控信号发生器的设计

1.功能要求

由c8051f020控制dds芯片来实现对输出信号的频率/相位调节,且可以实现多种频率设定功能,具有跳频、点频、扫频工作模式,并通过液晶显示器将频率值显示出来。

2.方案设计指标

1.采用12864F液晶显示器,可以显示设计者及课题名称,DDS输出频率为1HZ~10MHZ的正弦信号,LED标志。

2.DDS电路设计的选择

   主要有2种方案:

 (1).采用高性能的DDS专用单片电路的解决方案。主要有 Qualcomm、Sciteg、Stanford和AD等公司的单片电路.

 (2).采用低频正弦DDS单片电路的解决方案。主要有MicroLiner公司的ML2035.

由于本系统的频率要求比较高,用ML2035达不到指标,所以采用AD的AD9850.

关于AD9850的主要性能,可参看我BLOG前面的文章。

3.低通滤波器的设计

 由于输出实际上是时间极短的采样数据,所以采用椭圆低通滤波器。

4.系统框图

点击看大图

A. c8051f020的主要技术特点,可参看前面文章。

B. 128*64LCD可选取市面上常见液晶模块,不在此详解.

C.DDS电路的设计

1).AD98950的功能介绍

   F(out) = (△FCONB*fs) ÷(2的32次方)

 

zjw5000   写于2008-10-27

系统分类: 单片机   |    用户分类:    |    来源: 原创

该用户于2008-11-18 17:46:01编辑过该文章

评论(2) | 阅读(676)
发表于:2008-10-27 16:26:36
标签:AD9850  

1

AD9850

 
DDS芯片AD9850

AD9850AD公司生产的最高时钟为125 MHz、采用先进的CMOS技术的直接频率合成器,主要由可编程DDS系统、高性能模数变换器(DAC)和高速比较器3部分构成,能实现全数字编程控制的频率合成。

1.AD9850原理

AD9850 内含可编程DDS 系统和高速比较器,可实现全数字编程控制的频率合成。可编程DDS 系统的核心是相位累加器,由一个加法器和一个N位相位寄存器组成,N 一般为24~32。每来一个外部参考时钟,相位寄存器便以步长M 递加。相位寄存器的输出与相位控制字相加后可输入到正弦查询表地址上。正弦查询表包含一个正弦波周期的数字幅度信息,每一个地址对应正弦波中0°~360°范围的一个相位点。查询表把输入地址的相位信息映射成正弦波幅度信号,然后驱动DAC 输出模拟量。
相位寄存器每过2N/ M 个外部参考时钟后返回到初始状态一次,相应地正弦查询表
每经过一个循环也回到初始位置,从而使整个DDS 系统输出一个正弦波。输出的正弦波频率fout = M*fc/ 2N ,
fc 为外部参考时钟频率。
AD9850 采用32 位的相位累加器将信号截断成14 位输入到正弦查询表,查询表的输出再被截断成10 位后输入到DAC ,DAC 再输出两个互补的电流。DAC 满量程输出电流通过一个外接电阻RSET调节,RSET的典型值是3. 9kΩ(据小厮经验,此为关键)。将DAC 的输出经低通滤波后接到AD9850 内部的高速比较器上即可直接输出方波。在125MHz 的时钟下, 32 位频率控制字可使AD9850 输出频率分辨率达0. 0291Hz 。

2.控制字与时序

AD9850 有40 位控制字,32 位用于频率控制(低32位),5 位用于相位控制,1 位用于电源休眠( Powerdown) 控制,2 位用于选择工作方式。这40 位控制字可通过并行或串行方式输入到AD9850 。在并行装入方式中,通过8 位总线D0 —D7 将数据输入到寄存器,在W - CL K 的上升沿装入8位数据,并把指针指向下一个输入寄存器,在重复5 次之后再在FQ - UD 上升沿把40 位数据从输入寄存器装入到频率/ 相位数据寄存器(更新DDS 输出频率和相位) , 同时把地址指针复位到第一个输入寄存器。

没有实践就没有发言权,小厮不曾用过串行输入方式,所以对于串行送数不便多言!

AD9850 的复位(RESET) 信号为高电平有效,且脉冲宽度不小于5 个参考时钟周期。AD9850 的参考时钟频率一般远高于单片机的时钟频率(小厮所用为单片机89C51,使用12M晶振), 因此AD9850 的复位(RESET) 端可与单片机的复位端直接相连。

PS:据小厮经验,两位工作方式控制字一般写为00即可。

3.与单片机接口

其实,AD9850 有两种与微机并行口相连的评估版,并配有Windows 下运行的软, 可以作为应用参考,但运用单片机实现对DDS 的控制与微机实现的控制相比,具有编程控制简便、接口简单、成本低、容易实现系统小型化等优点。

W-CL K 和FQ-UD 信号都是上升沿有效,用MOVX @DPTR , A 指令向AD9850 传
送控制字时,P2.7经反相并与反相后的信号相与得到一上升沿送至AD9850 的W-CL K 脚,此时已送到总线上的数据将被AD9850 接收,连续五次将40 位的控制字全部发送以后,用MOVX A , @DPTR 指令产生FQ-UD 信号,使AD9850 更改输出频率和相位,此时读入到单片机内的数据实际上无任何意义。

系统分类: 单片机   |    用户分类:    |    来源: 原创

评论(0) | 阅读(141)
发表于:2008-10-27 15:27:34
标签:C8051F  

2

评论(0) | 阅读(130)
发表于:2008-10-22 15:12:00
标签:C51  

0

DS18B20(包含上位机)

上传网友的作品,DS18B20测温源码,含上位机。

源码:

A_BIT EQU 20h ;液晶十位数存放内存位置
B_BIT EQU 21h ;液晶个位数存放内存位置
C_BIT EQU 22H ;个位小数
D_BIT EQU 23H ;十位小数
E_BIT EQU 24H ;百位小数
F_BIT EQU 25H ;千位小数


RS BIT P1.0 ;这3位是液晶屏的控制信号,连接方式由具体硬件而定
RW BIT P1.1
E  BIT P1.2

ORG 0000H
            LJMP MAIN
ORG 0100H
MAIN:  
           LCALL   INIT_RS232
           CLR P1.3
           LCALL T_CONVERSION;调用读温度子程序
           LCALL T_FORMAT;将读出的2字节温度格式化
           LCALL DISPLAY;调用液晶显示子程序
           LCALL D1S;延时1秒后再测
           LJMP MAIN

;--------------DS18B20的温度转换子程序,具体时序请参考资料-------------------
T_CONVERSION:        LCALL INIT_1820;先复位DS18B20
                     JB FLAG1,T_C0
                     RET ; 判断DS1820是否存在  若DS18B20不存在则返回

T_C0:                MOV A,#0CCH ; 跳过ROM匹配
                     LCALL WRITE_1820
                     MOV A,#44H ; 发出温度转换命令
                     LCALL WRITE_1820
                     LCALL D1S   ;这里等待AD转换结束,12位的话要延时750m秒
                     LCALL INIT_1820;准备读温度前先复位
                     MOV A,#0CCH ; 跳过ROM匹配
                     LCALL WRITE_1820
                     MOV A,#0BEH ; 发出读温度命令
                     LCALL WRITE_1820
                     LCALL READ_1820; 将读出的温度数据保存到28H(TEMPER_H)和29H(TEMPER_L)处
                     RET

;------DS18B20复位初始化程序-----------------------------------------
INIT_1820:   SETB P1.6
                   NOP
                   CLR P1.6
                   MOV R0,#2 ;主机发出延时500微秒的复位低脉冲
INIT0:         MOV R1,#250
                   DJNZ R1,$
                   DJNZ R0,INIT0

                   SETB P1.6;然后拉高数据线
                   NOP

                   MOV R0, #15
INIT1:         JNB P1.6, INIT3;延时60us等待DS18B20回应
                   DJNZ R0, INIT1
                   LJMP INIT4 ; 超时而没有响应
INIT3:         SETB FLAG1 ; 置标志位,表示DS1820存在
                   LJMP INIT5
INIT4:         CLR FLAG1 ; 清标志位,表示DS1820不存在
                   LJMP INIT6
INIT5:         MOV R0, #120
                   DJNZ R0, $ ; 延时240us
INIT6:         SETB P1.6
                   RET

;---------写DS18B20的子程序(有具体的时序要求)-------------------------------------
WRITE_1820:   MOV R2,#8;一共8位数据
WR0:              CLR P1.6
                     MOV R3,#6
                     DJNZ R3,$
                     RRC A
                     MOV P1.6,C
                     MOV R3,#20
                     DJNZ R3,$
                     SETB P1.6
                     NOP
                     NOP
                     DJNZ R2,WR0
                     SETB P1.6
                     RET

;------读DS18B20的程序,从DS18B20中读出两个字节的温度数据--------------------------
READ_1820:      MOV R4,#2 ; 将温度高位和低位从DS18B20中读出
                MOV R1,#TEMPER_L ; 低位存入29H(TEMPER_L)
RE0:            MOV R2,#8
RE1:            SETB P1.6
                   NOP
                   NOP
                   CLR P1.6
                   NOP
                   NOP
                   SETB P1.6
                   MOV R3,#5
                   DJNZ R3, $
                   MOV C,P1.6
                   MOV R3,#20
                   DJNZ R3, $
                   RRC A
                   DJNZ R2,RE1
                   MOV @R1,A
                   DEC R1            ; 高位存入28H(TEMPER_H)
                   DJNZ R4,RE0
                   RET

;-----整合读出的两字节温度(关于DS18B20读出的2字节温度格式请参考资料)----------
T_FORMAT:         MOV A, #0FH
                  ANL A, TEMPER_L
                  MOV T_DF, A           ;获得小数部分(4位)

                  MOV A, TEMPER_L
                  SWAP A
                  MOV TEMPER_L, A

                  MOV A, TEMPER_H
                  SWAP A
                  MOV R0, #TEMPER_L
                  XCHD A, @R0

                  MOV T_INTEGER, A       ;获得整数部分(1字节)
                  RET

;-------液晶显示的子程序(显示前先格式转换)---------------------------------------
DISPLAY:             mov a, T_INTEGER
                     mov b,#10
                     div ab
                     mov A_BIT,a ;十位存在A_BIT
           mov B_BIT,b ;个位存在B_BIT
                     MOV A, T_DF
                     MOV R0, #C_BIT
                    MOV R2, #4
                D0: MOV B, #10
                     MUL AB
                     MOV B, #16
                     DIV AB
                     MOV @R0, A      ;从个位小数C_BIT,到十位D_BIT,百位E_BIT,千位F_BIT
                     INC R0
                     MOV A, B
                     DJNZ R2, D0
                     ;----二进制到ASCII码转换--------------
                     MOV A, #30H
                     ORL A_BIT, A
                     ORL B_BIT, A
                     ORL C_BIT, A
                     ORL D_BIT, A
                     ORL E_BIT, A
                     ORL F_BIT, A
                     ;-------------------------------------
                     LCALL INITIAL
                     MOV A, #10000000B                ; LINE1: DB 'Now is:',00H
                     LCALL   WRITE_INSTRUCTION
                     MOV   DPTR, #LINE1
                     LCALL   PR_STRING
                     MOV A, A_BIT
                     LCALL TX_CHAR
                     LCALL   WRITE_LCDDATA
                     MOV A, B_BIT
                 LCALL TX_CHAR
                     LCALL   WRITE_LCDDATA
                     MOV A, #2EH
                     LCALL TX_CHAR;'.'字符
                     LCALL   WRITE_LCDDATA
                     MOV A, C_BIT
                 LCALL TX_CHAR
                     LCALL   WRITE_LCDDATA
                     MOV A, D_BIT
                 LCALL TX_CHAR
                     LCALL   WRITE_LCDDATA
                     MOV A, E_BIT
                 LCALL TX_CHAR
                     LCALL   WRITE_LCDDATA
                     MOV A, F_BIT
                 LCALL TX_CHAR
                     LCALL   WRITE_LCDDATA
                     MOV A, #0DFH                        ;下面两个是摄氏度的数字符号
                 LCALL TX_CHAR
                     LCALL   WRITE_LCDDATA
                     MOV A, #43H
                 LCALL TX_CHAR
                     LCALL   WRITE_LCDDATA
                     MOV A, #0AH
                 LCALL TX_CHAR
                    
                     mov a, #11000000B                 ; LINE2: DB 'WANG XUE MIN!',00H
                     Lcall write_instruction
                     MOV   DPTR, #LINE2
                     LCALL   PR_STRING
                     RET

;---液晶屏初始化,具体请参考资料-------------------------------------------------
initial:         MOV   A, #01H
                       LCALL WRITE_INSTRUCTION
                       MOV   A, #38H
                       LCALL WRITE_instruction
                       MOV   A, #0FH
                       LCALL WRITE_instruction
                       MOV   A, #06H
                       LCALL WRITE_instruction
                       RET

;----写液晶指令的子程序------------------------------------------
WRITE_instruction: MOV P0, A
                               CLR RS ;写入控制命令
                               CLR RW
                               CLR E
                               LCALL DELAY
                               SETB E
                               RET

;----写液晶数据的子程序---------------------------------------------
write_lcddata:   MOV P0, A
                          SETB RS ;写入数据
                          CLR RW
                          CLR E
                          LCALL DELAY ;判断液晶模块是否忙 
                          SETB E
                          RET

;-----写行字符的子程序---------------------------------------------------------------
PR_STRING:   CLR    A
                   MOVC   A, @A+DPTR
                   JZ      END_PR
                   LCALL WRITE_LCDDATA
                   INC    DPTR
                   LJMP   PR_STRING
END_PR:       RET

;----查看液晶忙碌信号的子程序---------------------------------------------------------
DELAY:   MOV P0,#0FFH ;判断液晶显示器是否忙的子程序
             CLR RS
             SETB RW
             CLR E
             NOP
             SETB E
             JB P0.7,DELAY ;如果P1.7为高电平表示忙就循环等待
             RET
;---1mS延时(按12MHZ算)-----------------------------------------------------------------
D1mS:      MOV R7,#250
LOOP0:    NOP
              NOP
              DJNZ R7,LOOP0
              RET
;----1S延时(按12MHZ算)-----------------------------------------------------------------
D1S:       Mov R6,#4
LOOP2:    mov R5,#250
LOOP1:    LCALL D1mS
              DJNZ R5,LOOP1
              DJNZ R6,LOOP2
              RET
;-----------------------
TX_CHAR:
 JNB TI,$
 CLR TI
 MOV SBUF, A
 RET
;--------------------------------------------------------------------------------------
LINE1: DB 'NOW IS:',00H
LINE2: DB 'WANG XUE MIN',00H
END

 

系统分类: 单片机   |    用户分类:    |    来源: 整理

评论(0) | 阅读(203)
发表于:2008-10-22 15:11:26
标签:C51  

0

DS18B20(包含上位机)

上传网友的作品,DS18B20测温源码,含上位机。

源码:

A_BIT EQU 20h ;液晶十位数存放内