51单片机的红外遥控小车设计和制作的C语言程序

51单片机的红外遥控小车设计和制作的C语言程序,第1张

 论文摘要:本文介绍一款红外线遥控小车,以AT89S51单片机为核心控制器,用L289驱动直流电机工作,控制小车的运行。本御旁款小车具有红外线遥控手动驾驶、自动驾驶、寻迹前进等功能。本系统采用模块化设计,软件用C语言编写。转贴卜亩于 51论 文网 www.51lun-wen.cn一、设计任务和要求以AT98C51单片机为核心,制作一款红外遥控小车,小车具有自动驾驶,手动驾驶和循迹前进等功能。自动驾驶时,前进过程中可以避障。手动驾驶时,遥控控制小车前进、后退、左转、右转、加速等 *** 作。寻迹前进时小车还可以按照预先设计好的轨迹前进。转贴于 51论 文网 www.51lun-wen.cn二、系统组成及工作原理本系统由硬件和软件两部分组成。硬件部分主要完成红外编码信号的发射和接受、障碍物检测、轨迹检测、直流电机运行的发生等功能。软件主要完成信号的检测和处理镇弊橡、设备的驱动及控制等功能。AT89S51单片机查询红外信号并解码,查询各个检测部分输入的信号,并进行相应处理,包括电机的正反转,判断是否遇到障碍物,判断是否小车其那金中有出轨等。系统结构框图如图1所示。转贴于 51论 文网 www.51lun-wen.cn图1 系统结构框图三、主要硬件电路1、遥控发射器电路该电路的主要控制器件为遥控器芯片HT6221,如图2所示。HT6221将红外码调制成38KHZ的脉冲信号通过红外发射二极管发出红外编码。图2中D1是红外发射二极管,D2是按键指示灯,当有按键按下时D2点亮。

用DS1302+单片机比较简单 DS1302程序(51汇编)

推荐

1.每次上电,必须把秒寄存器高位(第7位)设置为0,时钟才能走时。

2.如果需要写入数据和时钟日历信息,必须把“写保护”寄存器设置成为0

内存数据定义

BitCnt data 3Ch 数据位计数器

ByteCnt data 3Dh 数据字节计数器

Command data 3Eh 命令字节地址

RcvDat DATA 40H 接收数据缓冲区

XmtDat DATA 50H 发送数据缓差弊冲区

端口位定义

IO_DATA bit P1.6 数据传送总线

SCLK bit P1.5时钟控制总线

RST bit P1.7 复位总线

RS BIT P3.5

RW BIT P3.6

EN BIT P3.7

ORG 0000H

ORG 0013H

LCALL JKS

AJMP KS

**************************** main program

ORG0030H

KS: CLR RST

MOV SP,#2AH

----LCD初始化----

CLR EN 使能端为0,液晶执行命令

INIT_LCD:

MOV A,#38H 双列显示,字形5*7点阵

ACALL WCOM

ACALL DELAY1

MOV A,#38H 双列显示,字形5*7点阵

ACALL WCOM

ACALL DELAY1

MOV A,#38H 双列显示,字形返庆游5*7点阵

ACALL WCOM

ACALL DELAY1

MOV A,#0CH 开显示,关光标

ACALL WCOM

ACALL DELAY1

MOV A,#01H 清除 LCD 显示屏

ACALL WCOM

ACALL DELAY1

MOV A,#06H 地址加1

ACALL WCOM

ACALL DELAY1

------------------------------------初始化1302-------------------------

SET1302:

LCALL Write_Enable写允许

LCALL Osc_Disable

LCALL Write_Multiplebyte初始化1302,将我们要设定的数据写入

LCALL Read_Multiplebyte将我们设定的漏销数据读出来

LCALL Osc_Enable

START:

ACALL LCD

LCALL Read_Multiplebyte

AJMP START

---------------------LCD显示-------------------------

LCD:

MOV A,#11001000B

LCALL WCOM

MOV A,#0显示时间

MOV A,42H

LCALL SSH2

MOV A,#00111010B

LCALL WDATA

MOV A,41H

LCALL SSH2

MOV A,#00111010B

LCALL WDATA

MOV A,40H

LCALL SSH2

MOV A,#11000000B

LCALL WCOM

MOV A,#0显示日期字符

MOV A,46H

LCALL SSH2

MOV A,#00101101B

LCALL WDATA

MOV A,44H

LCALL SSH2

MOV A,#00101101B

LCALL WDATA

MOV A,43H

LCALL SSH2

RET

SSH2:

MOV B,#16

DIV AB

MOV 58H,B

MOV 59H,A

MOV A,59H

MOV DPTR,#TAB

MOVC A,@A+DPTR

ACALL WDATA

MOV A,58H

MOV DPTR,#TAB

MOVC A,@A+DPTR

ACALL WDATA

RET

-----------------------------------------------------

写指令、数据使能子程序

-----------------------------------------------------

WCOM: 写指令使能

ACALL DELAY0

MOV P0,A

CLR RS

CLR RW

CLR EN

CLR EN

CLR EN

SETB EN

RET

WDATA: 写数据使能

ACALL DELAY0

MOV P0,A

SETB RS RS=H,RW=L,D0-D7=数据,E=高脉冲

CLR RW

CLR EN

CLR EN

CLR EN

SETB EN

RET

****判忙音****

DELAY0:

MOV P0,#0FFH

CLR RS

SETB RW

CLR EN

NOP

SETB EN

JB P0.7,DELAY0

RET

TAB:DB 00110000B,00110001B,00110010B,00110011B

DB 00110100B,00110101B,00110110B,00110111B

DB 00111000B,00111001B

********************************************************************************************

发送数据程序

名称:Send_Byte

描述:发送ByteCnt 个字节给被控器DS1302

命令字节地址在Command 中

所发送数据的字节数在ByteCnt 中发送的数据在XmtDat 缓冲区中

********************************************************************************************

Send_Byte:

CLR RST 复位引脚为低电平所有数据传送终止

NOP

CLR SCLK清时钟总线

NOP

SETB RST 复位引脚为高电平逻辑控制有效

NOP

MOV A,Command准备发送命令字节

MOV BitCnt,#08h 传送位数为8

S_Byte0:

RRC A 将最低位传送给进位位C

MOV IO_DATA,C 位传送至数据总线

NOP

SETB SCLK 时钟上升沿发送数据有效

NOP

CLR SCLK 清时钟总线

DJNZ BitCnt,S_Byte0 位传送未完毕则继续

NOP

S_Byte1: 准备发送数据

MOV A,@R0 传送数据过程与传送命令相同

MOV BitCnt,#08h

S_Byte2:

RRC A

MOV IO_DATA,C

NOP

SETB SCLK

NOP

CLR SCLK

DJNZ BitCnt,S_Byte2

INC R0 发送数据的内存地址加1

DJNZ ByteCnt,S_Byte1 字节传送未完毕则继续

NOP

CLR RST 逻辑 *** 作完毕清RST

RET

***************************************************************************************

接收数据程序

名称:Receive_Byte

描述:从被控器DS1302 接收ByteCnt 个字节数据

命令字节地址在Command 中

所接收数据的字节数在ByteCnt 中接收的数据在RcvDat 缓冲区中

***********************************************************************************

Receive_Byte:

CLR RST 复位引脚为低电平所有数据传送终止

NOP

CLR SCLK 清时钟总线

NOP

SETB RST 复位引脚为高电平逻辑控制有效

MOV A,Command 准备发送命令字节

MOV BitCnt,#08h 传送位数为8

R_Byte0:

RRC A 将最低位传送给进位位C

MOV IO_DATA,C 位传送至数据总线

NOP

SETB SCLK 时钟上升沿发送数据有效

NOP

CLR SCLK 清时钟总线

DJNZ BitCnt,R_Byte0 位传送未完毕则继续

NOP

R_Byte1: 准备接收数据

CLR A 清类加器

CLR C 清进位位C

MOV BitCnt,#08h 接收位数为8

R_Byte2:

NOP

MOV C,IO_DATA 数据总线上的数据传送给C

RRC A 从最低位接收数据

SETB SCLK 时钟总线置高

NOP

CLR SCLK 时钟下降沿接收数据有效

DJNZ BitCnt,R_Byte2 位接收未完毕则继续

MOV @R1,A 接收到的完整数据字节放入接收内存缓冲区

INC R1 接收数据的内存地址加1

DJNZ ByteCnt,R_Byte1 字节接收未完毕则继续

NOP

CLR RST 逻辑 *** 作完毕清RST

RET

--写保护寄存器 *** 作------------------------------------------

Write_Enable:

MOV Command,#8Eh 命令字节为8E

MOV ByteCnt,#1 单字节传送模式

MOV R0,#XmtDat 数据地址覆给R0

MOV XmtDat,#00h 数据内容为0 写入允许

ACALL Send_Byte 调用写入数据子程序

RET

当写保护寄存器的最高位为1 时禁止数据写入寄存器---------------

Write_Disable:

MOV Command,#8Eh 命令字节为8E

MOV ByteCnt,#1 单字节传送模式

MOV R0,#XmtDat 数据地址覆给R0

MOV XmtDat,#80h 数据内容为80h 禁止写入

ACALL Send_Byte 调用写入数据子程序

RET 返回调用本子程序处

当把秒寄存器的第7 位时钟停止位设置为0 时起动时钟开始---------

Osc_Enable:

MOV Command,#80h 命令字节为80

MOV ByteCnt,#1 单字节传送模式

MOV R0,#XmtDat 数据地址覆给R0

MOV XmtDat,#00h 数据内容为0 振荡器工作允许

ACALL Send_Byte 调用写入数据子程序

RET 返回调用本子程序处

当把秒寄存器的第7 位时钟停止位设置为1 时时钟振荡器停止HT1380 进入低功耗方式---------------

Osc_Disable:

MOV Command,#80h 命令字节为80

MOV ByteCnt,#1 单字节传送模式

MOV R0,#XmtDat 数据地址覆给R0

MOV XmtDat,#80h 数据内容为80h 振荡器停止

ACALL Send_Byte 调用写入数据子程序

RET 返回调用本子程序处

写入00 年6 月21 日星期三13 时59 分59---------------------

Write_Multiplebyte:

MOV Command,#0BEh 命令字节为BEh

MOV ByteCnt,#8 多字节写入模式此模块为8 个

MOV R0,#XmtDat 数据地址覆给R0

MOV XmtDat,#59h 秒单元内容为59h

MOV XmtDat+1,#59h 分单元内容为59h

MOV XmtDat+2,#13h 时单元内容为13h

MOV XmtDat+3,#21h 日期单元内容为21h

MOV XmtDat+4,#06h 月单元内容为06h

MOV XmtDat+5,#03h 星期单元内容为03h

MOV XmtDat+6,#0 年单元内容为00h

MOV XmtDat+7,#0 写保护单元内容为00h

ACALL Send_Byte 调用写入数据子程序

RET 返回调用本子程序处

读出寄存器0-7 的内容程序设置如下

Read_Multiplebyte:

MOV Command,#0BFh 命令字节为BFh

MOV ByteCnt,#8 多字节读出模式此模块为8 个

MOV R1,#RcvDat 数据地址覆给R1

ACALL Receive_Byte调用读出数据子程序

RET返回调用本子程序处

DELAY1: 延时10MS

MOV 21H,#75

D2:MOV 22H,#100

DJNZ 22H,$

DJNZ 21H,D2

RET

=============================================================================================

END

#include<reg51.h>

#include<intrins.h>

#define uchar unsigned char

#define uint unsigned int

sbit sda=P2^7

sbit scl=P3^6

sbit wp=P3^7

sbit lcden=P3^5

sbit lcdrs=P3^0

sbit lcdrw=P3^1

sbit modekey=P3^3

sbit setkey=P3^4

sbit DQ =P2^0 //定义通信端口销友带

//延时函数

static unsigned char HT,LT,beng //定义用告橡于存放温度值的高位

sbit second_ge=P2^6

sbit second_shi=P2^5

sbit min_ge=P2^4

sbit min_shi=P2^3

sbit hour_ge=P2^2

sbit hour_shi=P2^1

uchar num,num1,num2,num3,num4,num5,num6,num7,numtemp,tt,tempbuf,a,x,dis1,dis2,dis3,dat

uchar sbuf,mbuf,hbuf,wbuf,dbuf,mobuf,ybuf,keyV,key1buf,key2buf,miao,shi,fen,xin,ri,yue,nian

uchar code table[]={0x28,0x7e,0xa2,0x62,0x74,0x61,0x21,0x7a,0x20,0x60}//0123456789

uchar code table1[]="2010-01-13 WED"

uchar code table2[]="00:00:00 00.0 C"

uchar code table3[]="SUNMONTUEWEDTHUFRISAT"

uchar code month_day[]={0,32,30,32,31,32,31,32,32,31,32,31,32,30}

uchar code tempdottab[]={0,1,1,2,3,3,4,4,5,6,6,7,8,8,9,9}

void delay()

{ }

void delay1(uint x)

{

uchar a,b

for(a=xa>0a--)

for(b=100b>0b--)

}

//以下为LCD显示程序

void write_com(uchar com)

{

lcdrs=0

P1=com

delay1(5)

lcden=1

delay1(5)

lcden=0

}

void write_data(uchar date)

{

lcdrs=1

P1=date

delay1(5)

lcden=1

delay1(5)

lcden=0

}

void write_sfm(uchar add,uchar date)

{

uchar shi,ge

shi=date/10

ge=date%10

write_com(0x80+0x40+add)

write_data(0x30+shi)//地址自动加1

write_data(0x30+ge)

}

void write_nyr(uchar add,uchar date)

{

uchar shi,ge

shi=date/10

ge=date%10

write_com(0x80+add)

write_data(0x30+shi)//地址自动加1

write_data(0x30+ge)

}

void write_week(uchar add,uchar date)

{ uchar bai,shi,ge

bai=table3[date*3]

shi=table3[date*3+1]

ge=table3[date*3+2]

write_com(0x80+add)

write_data(bai)//地址自动加1

write_data(shi)

write_data(ge)

}

lcd_display()

{

miao=dis1

fen=dis2

shi=dis3

/亏芦/lcdrw=0

write_sfm(4,shi)

write_sfm(7,fen)

write_sfm(10,miao)

write_week(12,num4)

write_nyr(9,num5)

write_nyr(6,num6)

write_nyr(3,num7)

//lcdrw=1//必须置位,否则会与按键程序冲突

}

//DB18B20子程序

void delay2(unsigned int i) //

{

while(i--)

}

void delayms(unsigned int i) //延时 1MS

{ unsigned char j=0

for (i>0i--)

{ for (j=0j<125j++)

{}

}

}

//DB18B20初始化函数

Init_DS18B20(void)

{

unsigned char x=0

DQ = 1 //DQ复位

delay2(8) //稍做延时

DQ = 0 //单片机将DQ拉低

delay2(80)//精确延时 大于 480us

DQ = 1 //拉高总线

delay2(14)

x=DQ //稍做延时后 如果x=0则初始化成功 x=1则初始化失败

delay2(20)

}

//读一个字节

ReadOneChar(void)

{

unsigned char i=0

unsigned char dat = 0

for (i=8i>0i--)

{

DQ = 0// 给脉冲信号

dat>>=1 // 逐位右移

DQ = 1// 给脉冲信号

if(DQ) //DQ为1 时,表示收到高电平1

dat|=0x80 // 把收到的高电平置给DAT的最高位

delay2(4)

}

return(dat) //

}

//写一个字节

WriteOneChar(unsigned char dat)

{

unsigned char i=0

for (i=8i>0i--)

{

DQ = 0

DQ = dat&0x01 //把要发送的高电平或者低电平给DQ 发送出去

delay2(5)

DQ = 1

dat>>=1 //逐位右移

}

delay2(4)

}

//读取温度

void ReadTemperature()

{

unsigned char a=0

unsigned char b=0

Init_DS18B20() //调用初始化函数

WriteOneChar(0xCC)// 跳过读序号列号的 *** 作

//不需要验证序列号。

WriteOneChar(0x44)// 发送温度转换命令 启动温度转换

Init_DS18B20()

WriteOneChar(0xCC)//跳过读序号列号的 *** 作

WriteOneChar(0xBE)//

a=ReadOneChar() //读取温度值低位

b=ReadOneChar() //读取温度值高位

LT=tempdottab[a&0x0f]

//LT=(a&0xF0)?5:0 //这句话的意思如果问号前的语句为真(判断小数位的高位是否为1111),是的话,置小数位位5 则LT=5 如果假 LT=0

/*如果a是从18B20里读来的低8位值

xiaoshu1 = (a&0x0f)*10/16//小数第一位

xiaoshu2 = (a&0x0f)*100/16%10//小数第二位

xiaoshu=xiaoshu1*10+xiaoshu2//小数两位*/

HT=b<<4 //

HT+=(a&0xF0)>>4 //

}

void lcd_display_tempmain( )

{

//uchar k

if (HT>99) //

{

write_com(0x80+0x40+8)//数码管百显示"1",表示100度

write_data(1)

}

if (HT<1) // 如果温度低于1度

{

write_com(0x80+0x40+8)//数码管百显示"-",表示零下温度

write_data(0x2d)

}

write_com(0x80+0x40+12)// 显示小数位温度值

write_data(0x30+LT)

write_com(0x80+0x40+9)// 显示十位温度值

write_data(0x30+HT%100/10)

write_com(0x80+0x40+10)// 显示个位温度值

write_data(0x30+HT%10)

}

//以下为初始化程序

void init()

{

P2=0xff

delay()

scl=1

delay()

num=0

num4=xin=3

num5=ri=13

num6=mobuf=yue=1

num7=nian=10

tt=0

wp=0

modekey=1

setkey=1

TMOD=0x01//设置定时器0为工作方式1

TH0=(65536-10000)/256

TL0=(65536-10000)%256

//TH1=(65536-20000)/256

//TL1=(65536-20000)%256

EA=1//开总中断

ET0=1//开定时器0中断

//ET1=1

lcdrw=0

lcden=0

write_com(0x38)//显示模式设置

write_com(0x0c)//显示开关及光标设置

write_com(0x06)//光标书写设置

write_com(0x01)//清屏

write_com(0x80+0x00)//首行显示地址设置

for(num=0num<15num++)

{

write_data(table1[num])

delay1(5)

}

write_com(0x80+0x40)

for(num=0num<15num++)

{

write_data(table2[num])

delay1(5)

}

write_com(0x80+0x40+13)

write_data(0xdf)

ReadTemperature() //读取温度值

lcd_display_tempmain( ) //对读到的温度值进行处理

TR0=1//启动定时器0

//TR1=1

}

//以下为按键管理程序

uchar key()

{

if(modekey==1)

return(0)

delay1(10)

if(modekey==1)

return(0)

while(!modekey)

keyV++

if(keyV==9)

keyV=0

return(keyV)

}

void key1()

{

key1buf=key()

switch(key1buf)

{

case 1:

{

TR0=0

key2buf=1

write_com(0x80+0x40+6)

write_com(0x0f)

break

}

case 2:

{

TR0=0

key2buf=2

write_com(0x80+0x40+3)

write_com(0x0f)

break

}

case 3:

{

TR0=0

key2buf=3

write_com(0x80+0x40+0)

write_com(0x0f)

break

}

case 4:

{

TR0=0

key2buf=4

write_com(0x80+12)

write_com(0x0f)

break

}

case 5:

{

TR0=0

key2buf=5

write_com(0x80+8)

write_com(0x0f)

break

}

case 6:

{

TR0=0

key2buf=6

write_com(0x80+5)

write_com(0x0f)

break

}

case 7:

{

TR0=0

key2buf=7

write_com(0x80+0)

write_com(0x0f)

break

}

case 8:

{

key2buf=0

keyV=0

write_com(0x0c)

TR0=1

}

}

if(key2buf!=0)

{

if(setkey==0)

{

delay1(5)

if(setkey==0)

{

while(!setkey)

switch(key2buf)

{

case 1:

{

sbuf=miao

sbuf++

if(sbuf>=60)

sbuf=0

num1=miao=sbuf

write_sfm(6,miao)

write_com(0x80+0x40+6)

break

}

case 2:

{

mbuf=fen

mbuf++

if(mbuf>=60)

mbuf=0

num2=fen=mbuf

write_sfm(3,fen)

write_com(0x80+0x40+3)

break

}

case 3:

{

hbuf=shi

hbuf++

if(hbuf>=24)

hbuf=0

num3=shi=hbuf

write_sfm(0,shi)

write_com(0x80+0x40+0)

break

}

case 4:

{

wbuf=xin

wbuf++

if(wbuf>=7)

wbuf=0

num4=xin=wbuf

write_week(12,xin)

write_com(0x80+12)

break

}

case 5:

{

dbuf=ri

dbuf++

if(dbuf>=month_day[mobuf])

dbuf=1

num5=ri=dbuf

write_nyr(8,ri)

write_com(0x80+8)

break

}

case 6:

{

mobuf=yue

mobuf++

if(mobuf>=13)

mobuf=1

num6=yue=mobuf

write_nyr(5,yue)

write_com(0x80+5)

break

}

case 7:

{

ybuf=nian

ybuf++

if(ybuf>=100)

ybuf=0

num7=nian=ybuf

write_nyr(2,nian)

write_com(0x80+0)

break

}

}

}

}

}

}

void main()

{

init()

while(1)

{

key1()

}

}

void time0() interrupt 1

{

TH0=(65536-10000)/256

TL0=(65536-10000)%256

tt++

if(tt==100)

{

tt=0

ReadTemperature() //读取温度值

lcd_display_tempmain( ) //对读到的温度值进行处理

num1++

if(num1>=60)

{

num1=0

num2++

if(num2>=60)

{

num2=0

num3++

if(num3>=24)

{

num3=0

num4++

num5++

if(num4>=7)

num4=0

xin=num4

write_week(12,xin)

if(num5>=month_day[num6])

{

num5=1

num6++

if(num6>=13)

{

num6=1

num7++

if(num7>=100)

num7=0

nian=num7

write_nyr(2,nian)

}

yue=num6

write_nyr(5,yue)

}

ri=num5

write_nyr(8,ri)

}

shi=num3

write_sfm(0,shi)

}

fen=num2

write_sfm(3,fen)

}

miao=num1

write_sfm(6,miao)

/*if(HT>37|HT<20) // 判断温度范围

{beng=0} // 如果温度高于37度或者低于20度,则报警告示

else

beng=1*/

}

}

/* if( *year%400 == 0 || *year%100 != 0 &&*year%4 == 0 )

dayOfMonth[1] = 29*/


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12566711.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-26
下一篇 2023-05-26

发表评论

登录后才能评论

评论列表(0条)

保存