求有51单片机的开平方子程序

作者&投稿:弋殷 (若有异议请与网页底部的电邮联系)
51单片机与DS18B20程序~

  #include
  #include

  #define uchar unsigned char
  #define uint unsigned int

  sbit DQ = P2^2; //数据口define interface
  sbit dula = P2^6; //数码管段选
  sbit wela = P2^7; //数码管位选

  uint temp; //温度值 variable of temperature

  //不带小数点
  unsigned char code table[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
  0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
  //带小数点
  unsigned char code table1[] = {0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};


  /*************精确延时函数*****************/
  void delay(unsigned char i)
  {
  while(--i);
  }
  /******************************************
  此延时函数针对的是12Mhz的晶振
  delay(0):延时518us 误差:518-2*256=6
  delay(1):延时7us (原帖写"5us"是错的)
  delay(10):延时25us 误差:25-20=5
  delay(20):延时45us 误差:45-40=5
  delay(100):延时205us 误差:205-200=5
  delay(200):延时405us 误差:405-400=5
  *******************************************/

  /*****************DS18B20******************/

  void Init_Ds18b20(void) //DS18B20初始化send reset and initialization command
  {
  DQ = 1; //DQ复位,不要也可行。
  delay(1); //稍做延时
  DQ = 0; //单片机拉低总线
  delay(250); //精确延时,维持至少480us
  DQ = 1; //释放总线,即拉高了总线
  delay(100); //此处延时有足够,确保能让DS18B20发出存在脉冲。
  }

  uchar Read_One_Byte() //读取一个字节的数据read a byte date
  //读数据时,数据以字节的最低有效位先从总线移出
  {
  uchar i = 0;
  uchar dat = 0;
  for(i=8;i>0;i--)
  {
  DQ = 0; //将总线拉低,要在1us之后释放总线
  //单片机要在此下降沿后的15us内读数据才会有效。
  _nop_(); //至少维持了1us,表示读时序开始
  dat >>= 1; //让从总线上读到的位数据,依次从高位移动到低位。
  DQ = 1; //释放总线,此后DS18B20会控制总线,把数据传输到总线上
  delay(1); //延时7us,此处参照推荐的读时序图,尽量把控制器采样时间放到读时序后的15us内的最后部分
  if(DQ) //控制器进行采样
  {
  dat |= 0x80; //若总线为1,即DQ为1,那就把dat的最高位置1;若为0,则不进行处理,保持为0
  }
  delay(10); //此延时不能少,确保读时序的长度60us。
  }
  return (dat);
  }

  void Write_One_Byte(uchar dat)
  {
  uchar i = 0;
  for(i=8;i>0;i--)
  {
  DQ = 0; //拉低总线
  _nop_(); //至少维持了1us,表示写时序(包括写0时序或写1时序)开始
  DQ = dat&0x01; //从字节的最低位开始传输
  //指令dat的最低位赋予给总线,必须在拉低总线后的15us内,
  //因为15us后DS18B20会对总线采样。
  delay(10); //必须让写时序持续至少60us
  DQ = 1; //写完后,必须释放总线,
  dat >>= 1;
  delay(1);
  }
  }


  uint Get_Tmp() //获取温度get the temperature
  {
  float tt;
  uchar a,b;
  Init_Ds18b20(); //初始化
  Write_One_Byte(0xcc); //忽略ROM指令
  Write_One_Byte(0x44); //温度转换指令
  Init_Ds18b20(); //初始化
  Write_One_Byte(0xcc); //忽略ROM指令
  Write_One_Byte(0xbe); //读暂存器指令
  a = Read_One_Byte(); //读取到的第一个字节为温度LSB
  b = Read_One_Byte(); //读取到的第一个字节为温度MSB
  temp = b; //先把高八位有效数据赋于temp
  temp <<= 8; //把以上8位数据从temp低八位移到高八位
  temp = temp|a; //两字节合成一个整型变量
  tt = temp*0.0625; //得到真实十进制温度值
  //因为DS18B20可以精确到0.0625度
  //所以读回数据的最低位代表的是0.0625度
  temp = tt*10+0.5; //放大十倍
  //这样做的目的将小数点后第一位也转换为可显示数字
  //同时进行一个四舍五入操作。
  return temp;
  }


  /****************数码码动态显示函数**************/

  void Display(uint temp) //显示程序
  {
  uchar A1,A2,A3;
  A1 = temp/100; //百位
  A2 = temp%100/10; //十位
  A3 = temp%10; //个位

  dula = 0;
  P0 = table[A1]; //显示百位
  dula = 1; //打开段选,对应74573的锁存位,高电平不锁存
  dula = 0;

  wela = 0;
  P0 = 0x7e;
  wela = 1; //打开位选
  wela = 0;
  delay(0);

  dula = 0;
  P0 = table1[A2]; //显示十位,使用的是有小数点的数组(因为temp值扩大了10倍,虽然是十位,实际为个位)
  dula = 1;
  dula = 0;

  wela = 0;
  P0 = 0x7d;
  wela = 1;
  wela = 0;
  delay(0);

  P0 = table[A3]; //显示个位
  dula = 1;
  dula = 0;

  P0 = 0x7b;
  wela = 1;
  wela = 0;
  delay(0);
  }


  void main()
  {
  while(1)
  {
  Display(Get_Tmp());
  }
  }

与晶振有关,假设采用12M晶振
MOV R2 ,#08H ;1微秒,8次
MOV R1 ,#9AH ;1微秒,9A=154
MOV R0 ,#7CH ;1微秒,7C=124
DT1: DJNZ R0, DT1 ;2微秒
DJNZ R1, DT1 ;2微秒
DJNZ R2, DT1 ;2微秒,8*154*124*2=152768*2=305536
RET ;2微秒

大约0.3秒

;======================需要开平方的数入口地址在72~74H中,开方值70~71H中==================
KPF:
MOV 70H,#03H
MOV 71H,#0E8H
KPF1:
MOV R1,70H
MOV R2,71H
MOV R3,#00H
MOV R4,#00H
MOV R5,70H
MOV R6,71H
LCALL TWOBITMUL
MOV A,R2
MOV R1,A
MOV A,R3
MOV R2,A
MOV A,R4
MOV R3,A
MOV R4,72H
MOV R5,73H
MOV R6,74H
LCALL THREECOMPARE
JNC KPF2
MOV R1,70H
MOV R2,71H
MOV R3,#03H
MOV R4,#0E8H
LCALL TWOBITADD
MOV 70H,R1
MOV 71H,R2
AJMP KPF1
KPF2:
MOV R1,71H
MOV R2,72H
MOV R3,#03H
MOV R4,#0E8H
LCALL TWOBITDEC
MOV 71H,R1
MOV 72H,R2
KPF3:
MOV R1,70H
MOV R2,71H
MOV R3,#00H
MOV R4,#00H
MOV R5,70H
MOV R6,71H
LCALL TWOBITMUL
MOV A,R2
MOV R1,A
MOV A,R3
MOV R2,A
MOV A,R4
MOV R3,A
MOV R4,72H
MOV R5,73H
MOV R6,74H
LCALL THREECOMPARE
JNC KPF4
MOV R1,70H
MOV R2,71H
MOV R3,#00H
MOV R4,#64H
LCALL TWOBITADD
MOV 70H,R1
MOV 71H,R2
AJMP KPF3
KPF4:
MOV R1,71H
MOV R2,72H
MOV R3,#00H
MOV R4,#64H
LCALL TWOBITDEC
MOV 71H,R1
MOV 72H,R2
KPF5:
MOV R1,70H
MOV R2,71H
MOV R3,#00H
MOV R4,#00H
MOV R5,70H
MOV R6,71H
LCALL TWOBITMUL
MOV A,R2
MOV R1,A
MOV A,R3
MOV R2,A
MOV A,R4
MOV R3,A
MOV R4,72H
MOV R5,73H
MOV R6,74H
LCALL THREECOMPARE
JNC KPF6
MOV R1,70H
MOV R2,71H
MOV R3,#00H
MOV R4,#0AH
LCALL TWOBITADD
MOV 70H,R1
MOV 71H,R2
AJMP KPF5
KPF6:
MOV R1,71H
MOV R2,72H
MOV R3,#00H
MOV R4,#0AH
LCALL TWOBITDEC
MOV 71H,R1
MOV 72H,R2
KPF7:
MOV R1,70H
MOV R2,71H
MOV R3,#00H
MOV R4,#00H
MOV R5,70H
MOV R6,71H
LCALL TWOBITMUL
MOV A,R2
MOV R1,A
MOV A,R3
MOV R2,A
MOV A,R4
MOV R3,A
MOV R4,72H
MOV R5,73H
MOV R6,74H
LCALL THREECOMPARE
JNC KPF8
MOV R1,70H
MOV R2,71H
MOV R3,#00H
MOV R4,#01H
LCALL TWOBITADD
MOV 70H,R1
MOV 71H,R2
AJMP KPF7
KPF8:
MOV R1,71H
MOV R2,72H
MOV R3,#00H
MOV R4,#01H
LCALL TWOBITDEC
MOV 71H,R1
MOV 72H,R2
RET
;===========================双字节二进制乘法子程序
;被乘数的入口地址为R1~R2,乘数的入口地址为R5~R6,积在R1~R4
;中,都是高位在前
TWOBITMUL:
MOV A,R2
MOV B,R6
MUL AB
MOV R4,A
MOV R3,B
;--------------R2与R6相乘暂存部分积----------------------------
MOV A,R2
MOV B,R5
MUL AB
CLR C
ADDC A,R3
MOV R3,A
MOV R2,B
JNC NEXT1
INC R2
;-------------R2与R5相乘暂存部分积------------------------------
NEXT1:
MOV A,R1
MOV B,R6
MUL AB
CLR C
ADDC A,R3
MOV R3,A
JNC NEXT2
INC R2
CLR C
NEXT2:
MOV A,B
ADDC A,R2
JNC NEXT3
MOV R7,#01H
AJMP NEXT4
NEXT3:
MOV R7,#00H
NEXT4:
MOV R2,A
;--------------R1与R6相乘暂存部分积---------------------------
MOV A,R1
MOV B,R5
MUL AB
CLR C
ADDC A,R2
MOV R2,A
MOV R1,B
JNC FINISH9
INC R1
FINISH9:
MOV A,R7
ADD A,R1
MOV R1,A
RET
;================================双字字加法子程序===============================================
;==========================被加数入口地址为R1 R2 ,加数入口地址为R3 R4,和的出口地址为R1,R2========
TWOBITADD:
MOV A,R2
CLR C
ADDC A,R4
MOV R2,A
MOV A,R1
JNC TWOBITADD1
INC A
CLR C
TWOBITADD1:
ADD A,R3
MOV R1,A
RET
;=================================双字节数减法子程序
;====================被减数入口地址为R1 R2,减数入口地址;;R3 R4,差的出口地址为R1 R2===============
TWOBITDEC:
MOV A,R2
CLR C
SUBB A,R4
MOV R2,A
JNC TWOBITDEC1
DEC R1
CLR C
TWOBITDEC1:
MOV A,R1
SUBB A,R3
MOV R1,A
RET
;=================================双字节数比较大小子程序=============================================
;==================固定数入口地址为R1 R2 ,随机数入口地址为R3 R4, 比较结果为进位标志位==================
;==================进位位为1,固定数小于随机数,进位位为零,固定数大于随机数===========================
TWOCOMPARE:
CLR C
MOV A,R2
SUBB A,R4
MOV A,R1
JNC TWOCOMPARE1
CLR C
SUBB A,#01H
JC TWOCOMPARE2
TWOCOMPARE1:
CLR C
SUBB A,R3
TWOCOMPARE2:
RET


单片机对TH0,TL0赋值
是一样的,第一种是65536-10000=55536,而55536转换成是十六进制就是D8F0,TH0=0XD8是高8位,而TL0=0xF0是低8位。第二个TH0= -10000\/256;TL0 =-10000%256;相当于:TH0= 65536-10000\/256;TL0 =65536-10000%56;那运算之后就是TH0=55536\/256;TL0 =55536%256;.55536\/256相当于高8...

怎么清点一堆钢板的数量
另一种方法需要高成本,激光打字机安装在自动开平线出板口,在自动开平线安装行程,安装计数器、触发器、数显、数据传输单片机,当行程出板的时候触发计数,将数字传输到激光打字机,激光打字机向钢板角上打印数字,打印好了后继续下一个行程。这套设备成本很高,但是有作用,开平完了你会发现钢板有编号了...

龙港区19596018916: 51单片机汇编语言.求两个数的平方和. -
虫唐复方: AAA EQU 30HBBB EQU 31HCCC EQU 40HORG 8000H MAIN: MOV R3,#0 ;清零MOV A,AAAACALL SQRT ;调用求平方子程序MOV R3,AMOV A,BBBACALL SQRT ;调用求平方子程序ADD A,R3MOV R3,AMOV CCC,R3SJMP $ SQRT: MOV DPTR,#TABMOVC A,@A+DPTRRET TAB: DB 0,1,4,9,16DB 25,36,49,64,81END

龙港区19596018916: 求51单片机,用1602lcd显示的简易计算器的程序.除了加减乘除,还要有开平方和平方的 -
虫唐复方: 电路图:把8位数据线接到单独一个P*口上,其他CS,RS,WR,RD分别接到另一个数据口上,再就是电源和地接上.程序:需要你提供IC型号的,不同的IC指令不同

龙港区19596018916: 单片机汇编语言中,调用子程序求A的平方,那子程序怎么表示 -
虫唐复方: ;…… MOV A, #10 ;预置数 LCALL PF ;调用子程序;……;…… PF: MOV B, A MUL AB RET END

龙港区19596018916: 单片机中计算平方子程序该如何写(不使用查表法) -
虫唐复方: 头文件包含math.h 调用pow()函数就可以了

龙港区19596018916: 51单片机汇编语言 编乘法和除法子程序 -
虫唐复方: ;(r3r2r1r0) = (r7r6) * (r5r4), r4-r7 unchanged mul_word:mov b,r6mov a,r4mul abmov r0,amov r1,bmov r2,#0mov r3,#0mov a,r7mov b,r4mul abadd a,r1mov r1,amov a,r2addc a,bmov r2,aclr aaddc a,r3mov r3,amov a,r6mov b,r5...

龙港区19596018916: 求一段51单片机的程序 -
虫唐复方: sbit p1=p1^0; sbit p2=p1^0; void main() { aa=0;TMOD=0x01;TH0=(65536-50000)/256;TL0=(65536-50000)%256;EA=1; //开总中断ET0=1; //开启T0中断TR0=1; //启动T0定时器 , 以上是用定时器0.if(aa==216000) //10800*50=3个小时...

龙港区19596018916: 急求高手给写一个51单片机程序~注意:只要汇编语言~不要C语言~~急急急~~~~~~~~ -
虫唐复方: 查询方式:ORG 0000H AJMP MAIN MAIN: MOV P1,#01H MOV R0,#8 MOV A,P1 XU: RL A MOV P1,A ACALL DELAY DJNZ R0,XU AJMP MAIN DELAY: MOV R0,#0FFH ONE:MOV R1,#0FFH TWO:MOV R2,#02H THE:DJNZ R2,THE DJNZ R1,...

龙港区19596018916: 求能使51单片机输出频率可调的方波的程序 -
虫唐复方: ADC0809好多讲单片机的书中都直接有例子的,输出方波就设为512ms的周期吧,设置1ms为单位的定时器,0809读到的是0~255的数值,转换一下就变成256-就可以了,然后*2就是正周期的时长.根据读出的数值,在1ms中处理就可以了

龙港区19596018916: 51单片机的一个简单程序 -
虫唐复方: ORG 0000H LJMP MAIN ORG 0030H MAIN:MOV A,P0 ANL A,#1EH CJNE A,#02H,MAIN1 SETB P1.1 CLR P1.2 CLR P1.8 SJMP MAINMAIN1:CJNE A,#04H,MAIN2 CLR P1.1 SETB P1.2 CLR P1.8 SJMP MAINMAIN2:CJNE A,#...

龙港区19596018916: 求写一段简单的51单片机C语言代码 -
虫唐复方: 单片机检测高电平.1、可以用外部中断,外接激光传感器最好用普通光耦隔离一下,顺便改成低电平触发单片机中断.然后用位移指令移动跑马灯,然后计数值加1. 2、可以用循环检测,也建议用光耦隔离先,在MAIN里面不断检测P00,发现变化后,再次检测以便确认,确认后同样位移一下跑马灯,然后计数加1.

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网