当前位置:   article > 正文

51单片机详解

51单片机

前言

这是我对这几个月学习51单片机的一些汇总,谈谈对51的一些看法,51大致就是对定时器,计算器,中断,串口的一些操作,前面我浅谈一下51的基本操作,后面我会对Sg-90舵机,超声波,LCD1602,DHT11温湿度传感器,IIC-OLED,HC-05蓝牙模块,esp8266-01sWI-FI模块,4G模块,4驱小车进行一个详细的汇总,希望能对大家有所帮助。

文章目录

  • 前言
  • 一、单片机入门
  • 1.什么是单片机
  • 2.单片机工作的基本时序
  • 3.数字电路基础
  • 4.二进制逻辑运算
  • 6.89C52的引脚图
  • 二、单片机的一些项目
    • 1.点亮一个LED&按键点亮
    • 2.LED循环点亮
    • 3.震动传感器介绍
    • 4.震动传感器点亮Led&震动传感器触发继电器点亮Led
    • 5.433接发模块&Relay做一个简易的报警器
    • 6.定时器详解
    • 7.中断详解
    • 8.利用舵机&超声波通过中断&定时器做一个自动垃圾桶
    • 9.UART串口详解
    • 10.利用串口发一个字符到上位机
    • 11.通过发送发送字符串到上位机
    • 12.通过串口用HC-05蓝牙模块,手机连接蓝牙点亮一个LED
    • 13.通过esp8266WI-FI模块通过上位机点亮一个LED
    • 14.通过4GI模块通 过上位机点亮一个LED
    • 15.Lcd1602详解
    • 16.DTH11温湿度详解
    • 17.IIC_OLED详解
    • 18.四驱小车
  • 总结

一、单片机入门

1.什么是单片机

单片机是一种集成电路芯片,采用超大规模集成技术把具有处理数据能力的中央处理器CPU、随机存储器ROM、只读存储器RAM、定时器/计算器、中断系统和IO口等功能集成到一块硅片上构成的一个小型计算机,从当时的4为、8位发展到现在的300M的高速单片机。

2.单片机工作的基本时序

我们都知道在学校是通过铃声来控制所有班级的上下课时间,我们都知道单片机执行指令的过程就是从ROM取出一条指令执行来完成它在各个地方的作用,那它什么时候取指令这个是顺序呢?这里引入一个时序的周期,每访问一次ROM的时间,就是一个机器周期的时间

1个机器周期 = 6个状态周期 = 12个时钟(振荡)周期  

时钟周期:即单片机的基本时间单位,若晶体的频率=12MHZ,那时钟周期 = 1/12MHZ,一个时钟周期 = 1/12MHZ = 1/12000 000每秒

机器周期:即12x1/12 000 000 =0.000001s = 1us,访问一次ROM取指令的时间就是1us

3.数字电路基础 

电平特性

数字电路中只有两种电平:高电平和低电平

高电平:5v或者3.3v,取决与单片机电源

低电平:0V

RS232电平:计算机串口的电平

高电平:-12v

低电平:+12v

我们跟电脑通信的时候,要通过元器件将单片机的电平转换成电脑能识别的电平,才能跟电脑进行通信。

4.二进制逻辑运算

"与"运算

有0得0,全1才1

1&1 = 1,1&0 = 0; 0&0 = 0;

"或"运算

有1得1,全0才0;

1|1 = 1;1|0 = 1;0|0 = 0;

"非"运算

~1 = 0;~0 = 1;

6.89C52的引脚

 二、单片机的一些项目

1.点亮一个LED&按键点亮

通过sbit访问单片机P2^0口,给它一个低电平,使它点亮

  1. #include <REGX52.h>
  2. sbit led = P2^0;//sbit作用是定义特殊功能寄存器的位变量 此时变量led就保存了p2^0的地址
  3. void main()
  4. {
  5. led = 0;//通过看原理图,这个io口的led是低电平触发
  6. }

通过单片机自带的按键使它点亮

  1. #include <REGX52.h>
  2. sbit led = P2^0;
  3. sbit key_open = P3^1;
  4. sbit key_close = P3^2;
  5. void main()
  6. {
  7. led = 1;//先默认让led关
  8. while(1)
  9. {
  10. if(key_open == 0)//当按下key_open它会的到一个低电平
  11. {
  12. led = 0;//按下按键我打开led
  13. }
  14. if(key_close == 0)//按下key_close,就关闭led
  15. {
  16. led = 1;
  17. }
  18. }
  19. }

 这里是通过按键开关来控制点亮了led的

2.LED循环点亮

  1. #include <REGX52.h>
  2. #include <intrins.h>
  3. void main()
  4. {
  5. P2 = 0xfe;//因为led是低电平点亮 0xfe = 1111 1110,我们先让第0位点亮
  6. while(1)
  7. {
  8. Delay1000ms();
  9. P2 = P2 << 1;//然后依次左移一位就= 1111 1101,让第1位点亮,后面依次操作
  10. //循环到第7=0111 1111 但是之前每循环左移都给了低电平
  11. if(P2 == 0x00)//所以当 = 0111 1111 的时候重新给它赋值位0xfe
  12. {
  13. P2 = 0xfe;
  14. }
  15. }
  16. }
  17. void Delay1000ms() //延迟函数
  18. {
  19. unsigned char i, j, k;
  20. _nop_();
  21. i = 8;
  22. j = 154;
  23. k = 122;
  24. do
  25. {
  26. do
  27. {
  28. while (--k);
  29. } while (--j);
  30. } while (--i);
  31. }

3.震动传感器介绍

 通过震动点亮led

  1. #include <REGX52.h>
  2. #include <intrins.h>
  3. sbit shake = P0^0;
  4. sbit led = P2^0;
  5. void main()
  6. {
  7. led = 1;
  8. while(1)
  9. {
  10. if(shake == 0)//当发生震动 就点亮led
  11. {
  12. led = 0;
  13. }
  14. }
  15. }

4.震动传感器点亮Led&震动传感器触发继电器点亮Led

通过震动让继电器把接在继电器上的灯点亮

  1. #include <REGX52.h>
  2. #include <intrins.h>
  3. sbit shake = P0^0;
  4. sbit relay = P0^1;
  5. void main()
  6. {
  7. while(1)
  8. {
  9. if(shake == 0)//当发生震动打开继电器
  10. {
  11. relay = 0;
  12. }
  13. }
  14. }

5.433接发模块&Relay做一个简易的报警器

通过433收发模块按下打开继电器让报警器响,在按一下让它停止响,当然你也可以在配一个震动传感器,如果发生震动就响,在按一下就停止响。

  1. #include <REGX52.h>
  2. #include <intrins.h>
  3. sbit d0 = P0^0;
  4. sbit d1 = P0^1;
  5. sbit relay = P0^7;
  6. void main()
  7. {
  8. while(1)
  9. {
  10. if(d0 == 1)
  11. {
  12. relay = 0;
  13. }
  14. if(d1 == 1)
  15. {
  16. relay = 1;
  17. }
  18. }
  19. }

 6.定时器详解

51单片机有两组定时器,一组是T0,一组是T1,因为几个定时/计数,所以称为定时器。定时器的本质就是每过一个机器周期加1

定时器一共有4个模式

GATE =1,要用软件使TR0/TR1置1,才能开始工作,同时外部中断INT0/1为高电平,才能启动定时器 

C/T = 0是定时模式,=1是计数模式

  1. #include <REGX52.h>
  2. #include <intrins.h>
  3. sbit led = P2^0;
  4. void Delay1000ms() //延迟函数
  5. {
  6. unsigned char i, j, k;
  7. _nop_();
  8. i = 8;
  9. j = 154;
  10. k = 122;
  11. do
  12. {
  13. do
  14. {
  15. while (--k);
  16. } while (--j);
  17. } while (--i);
  18. }
  19. void Time_Init()
  20. {
  21. TMOD = 0x01;
  22. TL0 = 0x20; //设置定时初值1ms,定时器初值=216次方(因为我选的模式1)—x)x12/你单片机晶振的频率 = 你要设的初值(us)求出的x转换成16 进制就行了
  23. TH0 = 0xD1;
  24. TR0 = 1;
  25. TF0 = 0;
  26. }
  27. void main()
  28. {
  29. int num = 0;
  30. Time_Init();
  31. led = 1;//默认led为关的状态
  32. while(1)
  33. {
  34. if(TF0 == 1)//定时好了溢出
  35. {
  36. ++num;//每溢出一次加1
  37. TL0 = 0x20; //设置定时初值
  38. TH0 = 0xD1;
  39. }
  40. if(num == 1000)//加到1000 也就是1s 打开led
  41. {
  42. led = !led;
  43. }
  44. }
  45. }

7.中断详解

比如:你正在喝奶茶,此时发生了一个紧急事情,你就会先暂停喝奶茶,转而取处理这个紧急事情,等紧急事情处理完了,你就可以继续和奶茶了。我们把这种紧急事情叫做中断。但是如果你喝奶茶期间发生了许多事情,那就要按照紧急事情的优先级来处理。

  1. #include <REGX51.H>
  2. sbit led = P2^0;
  3. int cnt = 0;
  4. void Time_Init()
  5. {
  6. TMOD = 0x10;
  7. TL1 = 0x18; //设置定时初值
  8. TH1 = 0xFC;
  9. TR1 = 1;
  10. TF1 = 0;//现在还没有溢出,先让他=0
  11. ET1 = 1;//用的T1就必须用T1中断通道
  12. EA = 1;
  13. }
  14. void main()
  15. {
  16. Time_Init();
  17. led = 1;
  18. while(1);
  19. }
  20. void zd() interrupt 3
  21. {
  22. TL1 = 0x18;
  23. TH1 = 0xFC;
  24. cnt++;
  25. if(cnt == 500)
  26. {
  27. cnt = 0;
  28. led =!led;
  29. }
  30. }

8.利用舵机&超声波通过中断&定时器做一个自动垃圾桶

超声波测距

  1. #include <regx52.h>
  2. sbit trig = P0^1;//发送超声波,要发送超声波,必须给trig一个10us以上的高电平
  3. sbit echo = P0^0;//判断超声波什么时候发送和什么时候接收
  4. sbit led = P2^0;
  5. void Delay10us() //@11.0592MHz
  6. {
  7. unsigned char i;
  8. i = 2;
  9. while (--i);
  10. }
  11. void trig10us()
  12. {
  13. trig = 0;
  14. trig = 1;
  15. Delay10us();
  16. trig = 0;
  17. }
  18. void Time1_Init()
  19. {
  20. TMOD = 0x10;//choose 16bit 计数
  21. TL1 = 0;
  22. TH1 = 0;
  23. }
  24. void main()
  25. {
  26. double time;
  27. double dis;
  28. Time1_Init();
  29. while(1)
  30. {
  31. trig10us();
  32. while(echo == 0);//判断超声波说明时候发送
  33. TR1 = 1;//开始定时
  34. while(echo == 1);//判断超声波什么时候返回
  35. TR1 = 0;//停止计时
  36. time = (TH1 *256 + TL1)*1;//TL1和TH1是所计的数,1是机器周期1us,time就是超声波去的时间和返回的时间
  37. dis = (time/2)*0.034;//因为time存放的是去和返回的时间,所以要除以2,超声波测距是340m/s换算成 34000cm/s = 34cm/ms = 0.034cm/us
  38. if(dis < 10)
  39. {
  40. led = 0;//open led
  41. }
  42. else
  43. {
  44. led = 1;
  45. }
  46. TH1 = 0;
  47. TL1 = 0;
  48. }
  49. }

舵机 

  1. /*
  2. 控制舵机是通过占空比来控制的,也就是在单位时间内,你控制让它得到多少高电平
  3. sg90舵机最高频率是50Mhz 周期就是0.02s = 20ms,我们字舵机20ms这个周期内给它高电平控制舵机角度
  4. 0° = 0.5ms
  5. 45° = 1ms
  6. 90° = 1.5ms
  7. 135°= 2ms
  8. 180°= 2.5ms
  9. */
  10. #include <regx52.h>
  11. #include <intrins.h>
  12. sbit sg90 = P0^7;
  13. int jd;//用于控制舵机角度
  14. int cnt;//用于计数来判断定时器中断溢出
  15. void Time0_Init()
  16. {
  17. TMOD = 0x01;
  18. TL0 = 0x33; //定时器第八位初始化
  19. TH0 = 0xFE;//定时器高八位初始化 设置定时05ms
  20. TR0 = 1;
  21. TF0 = 0;
  22. ET0 = 1;
  23. EA = 1;
  24. }
  25. void Delay1000ms() //延迟函数
  26. {
  27. unsigned char i, j, k;
  28. _nop_();
  29. i = 8;
  30. j = 1;
  31. k = 243;
  32. do
  33. {
  34. do
  35. {
  36. while (--k);
  37. } while (--j);
  38. } while (--i);
  39. }
  40. void main()
  41. {
  42. Time0_Init();
  43. jd = 1;
  44. cnt = 0;
  45. while(1)
  46. {
  47. jd = 5;
  48. cnt = 0;
  49. Delay1000ms();
  50. jd = 1;
  51. cnt = 0;
  52. Delay1000ms();
  53. }
  54. }
  55. void zd() interrupt 1
  56. {
  57. TL0 = 0x33;
  58. TH0 = 0xFE;
  59. cnt++;
  60. if(cnt <= jd)
  61. {
  62. sg90 = 1;
  63. }
  64. else
  65. {
  66. sg90 = 0;
  67. }
  68. if(cnt == 40)
  69. {
  70. cnt = 0;
  71. }
  72. }

垃圾桶

  1. #include <regx52.h>
  2. #include <intrins.h>
  3. sbit led = P2^0;
  4. sbit trig = P0^1; //超声波发送 给trig至少10us高电平
  5. sbit echo = P0^0;//怎么知道他开始发和接受的返回波
  6. sbit dj = P0^7;
  7. sbit key = P3^1;
  8. int cnt = 0;
  9. int jd;
  10. void Time0_Init()
  11. {
  12. TMOD &= 0xF0;
  13. TMOD |= 0x01;
  14. TL0 = 0x33; //定时器第八位初始化
  15. TH0 = 0xFE;//定时器高八位初始化 设置定时05ms
  16. TR0 = 1;//开始定时
  17. TF0 = 0;//定时器溢出标志位
  18. EA = 1;//中断允许总开关
  19. ET0 = 1;//T0中断允许开关
  20. }
  21. void Delay2500ms() //@11.0592MHz
  22. {
  23. unsigned char i, j, k;
  24. _nop_();
  25. i = 18;
  26. j = 131;
  27. k = 103;
  28. do
  29. {
  30. do
  31. {
  32. while (--k);
  33. } while (--j);
  34. } while (--i);
  35. }
  36. void Delay10us() //给trig一个10us延时
  37. {
  38. unsigned char i;
  39. i = 2;
  40. while (--i);
  41. }
  42. void Time1_Init()//初始化定时器
  43. {
  44. TMOD = 0x10;
  45. TH1 = 0;//0开始定时
  46. TL1 = 0;
  47. }
  48. void trig10()//给trig一个10us高电平
  49. {
  50. trig = 0;
  51. trig = 1;//向外发送
  52. Delay10us();
  53. trig = 0;//恢复
  54. }
  55. double Read_Csb()
  56. {
  57. double dis;
  58. double time;
  59. TH1 = 0;//0开始定时
  60. TL1 = 0;
  61. trig10();//发送一个信号
  62. while(echo == 0);//通过echo从高电平跳转到低电平知道已经开始发送信号了
  63. TR1 = 1;//信号发送开始定时
  64. while(echo == 1);//通过从低电平跳转到高电平知道波回来了
  65. TR1 = 0;//波回来了结束定时
  66. time=(TH1 * 256 + TL1)*1;//us为单位 计算中间进过的时间 记得数TH0和TL0相加 就是TH0左移8位 移1= 28= 256*1.085一个机器周期
  67. dis = time / 2* 0.034;//距离 = 340m/s = 34000cm/s = 34cm/ms = 0.034cm/us 时间来回两次 / 2
  68. return dis;
  69. }
  70. void main()
  71. {
  72. double dis;
  73. Time1_Init();//初始化定时器
  74. Time0_Init();
  75. jd = 1;
  76. cnt = 0;
  77. led = 1;
  78. while(1)
  79. {
  80. dis = Read_Csb();
  81. if(dis < 10 || key == 0)
  82. {
  83. led = 0;
  84. jd = 5;
  85. Delay2500ms();
  86. }
  87. else
  88. {
  89. led = 1;
  90. jd = 1;
  91. }
  92. }
  93. }
  94. void zd() interrupt 1 //控制脉冲
  95. {
  96. cnt++;
  97. TL0 = 0x33;
  98. TH0 = 0xFE;
  99. if(cnt <= jd)
  100. {
  101. dj = 1;
  102. }
  103. else
  104. {
  105. dj = 0;
  106. }
  107. if(cnt == 40)
  108. {
  109. cnt = 0;
  110. }
  111. }

9.UART串口详解

串口通信

1.单工   只有一根线,只能单向传输
2.半双工 有两根线Tx、Rx,交叉连接,但是任何时候只有一个方向传输和接收
3.全双工 有两根线可以在两个方向上传输

同步和异步通信

1.同步通信 发送数据和,等待接收方回应了,才能继续发送下个数据
同步通信 必须保持双方在同一个时钟
2.异步通信 发送数据后,不等待接收方的回应,继续发送下个数据
异步通信 因为发送效率低,所以每发送一个字符,要加开始位和停止位,还要配置波特率

10.发送一个字符到上位机

  1. #include <REGX51.H>
  2. #include <intrins.h>
  3. void UART_Init()
  4. {
  5. PCON = 0x00;//波特率不翻倍
  6. SCON = 0x50;//sm0 sm1 sm2 ren rb8 tb8 ti ri 每发送一个数据ti必须复位 每接收一个数据ri必须复位 ren = 1允许接收
  7. TMOD = 0x20;//波特率配置 方式1 9600 =(2smod/32)*t1的溢出率
  8. TH1 = 0XFD;//t1溢出率 = (频率/32)*(256 -TH1)
  9. TL1 = 0xFD;
  10. TR1 = 1;//打开定时器1
  11. }
  12. void Delay10000ms() //@11.0592MHz
  13. {
  14. unsigned char i, j, k;
  15. _nop_();
  16. i = 71;
  17. j = 10;
  18. k = 171;
  19. do
  20. {
  21. do
  22. {
  23. while (--k);
  24. } while (--j);
  25. } while (--i);
  26. }
  27. void main()
  28. {
  29. UART_Init();
  30. while(1)
  31. {
  32. Delay10000ms();
  33. SBUF = 'a';//每个一秒发送一个字符
  34. }
  35. }

11.发送一个字符串到上位机

  1. #include <REGX51.H>
  2. #include <intrins.h>
  3. void UART_Init()
  4. {
  5. SCON = 0x50;
  6. TMOD = 0x20;
  7. TH1 = 0XFD;
  8. TL1 = 0xFD;
  9. TR1= 1;
  10. }
  11. void Send_Bit(char Data)
  12. {
  13. SBUF = Data;
  14. while(!TI);
  15. TI = 0;
  16. }
  17. void Send_String(char * p)
  18. {
  19. while(*p != '\0')
  20. {
  21. Send_Bit(*p);
  22. p++;
  23. }
  24. }
  25. void Delay1000ms() //@11.0592MHz
  26. {
  27. unsigned char i, j, k;
  28. _nop_();
  29. i = 8;
  30. j = 1;
  31. k = 243;
  32. do
  33. {
  34. do
  35. {
  36. while (--k);
  37. } while (--j);
  38. } while (--i);
  39. }
  40. void main()
  41. {
  42. UART_Init();
  43. while(1)
  44. {
  45. Delay1000ms();
  46. Send_String("iverson");
  47. }
  48. }

12.通过串口用HC-05蓝牙模块,手机连接蓝牙点亮一个LED 

  1. #include <REGX51.H>
  2. #include <intrins.h>
  3. sbit led =P2^0;
  4. void UART_Init()
  5. {
  6. SCON = 0x50;
  7. TMOD = 0x20;
  8. TH1 = 0XFD;
  9. TL1 = 0xFD;
  10. TR1 = 1;
  11. ES = 1;
  12. EA = 1;
  13. }
  14. void Delay1000ms() //@11.0592MHz
  15. {
  16. unsigned char i, j, k;
  17. _nop_();
  18. i = 8;
  19. j = 1;
  20. k = 243;
  21. do
  22. {
  23. do
  24. {
  25. while (--k);
  26. } while (--j);
  27. } while (--i);
  28. }
  29. void main()
  30. {
  31. UART_Init();
  32. while(1)
  33. {
  34. Delay1000ms();
  35. SBUF = 'a';
  36. }
  37. }
  38. void zd() interrupt 4//串口中断
  39. {
  40. if(RI == 1)
  41. {
  42. RI = 0;
  43. if(SBUF == 'o')
  44. {
  45. led = 0;
  46. }
  47. if(SBUF == 'c')
  48. {
  49. led = 1;
  50. }
  51. }
  52. }

 13.通过esp8266WI-FI模块通过上位机点亮一个LED

  1. /*
  2. 就是在同一个局域网 服务器先连接WiFi 获得WiFiIP esp826601s在通过WIFIIP连接服务器
  3. 单片机通过串口发送数据给esp826601s esp826601s接受该AT数据连接 WIFI 和 服务器等
  4. 就开始实现数据传输
  5. AT+CWMODE=3 //1. 是station(设备)模式 2.是AP(路由)模式 3.是双模
  6. OK
  7. AT+CWJAP="TP-LINK_3E30","18650711783" //指令
  8. WIFI CONNECTED //结果
  9. WIFI GOT IP //结果
  10. AT+CIFSR //指令
  11. +CIFSR:APIP,"192.168.4.1" 当esp826601s做路由的IP
  12. +CIFSR:APMAC,"4e:75:25:0d:ae:2f"
  13. +CIFSR:STAIP,"192.168.0.148"
  14. +CIFSR:STAMAC,"4c:75:25:0d:ae:2f"
  15. OK
  16. AT+CIPSTART="TCP","192.168.0.113",8888 //指令,注意双引号逗号都要半角(英文)输入
  17. CONNECT //结果:成功
  18. OK //结果:成功
  19. AT+CIPSEND=4 // 设置即将发送数据的长度 (这里是4个字节)
  20. >CLCA // 看到大于号后,输入消息,CLCA,不要带回车
  21. Response :SEND OK //结果:成功
  22. //注意,这种情况下,每次发送前都要先发送AT+CIPSEND=长度 的指令,再发数据!
  23. AT+CIPMODE=1 //开启透传模式
  24. Response :OK
  25. +++退出透传模式
  26. AT+CIPSEND //带回车
  27. Response: > //这个时候随意发送接收数据咯
  28. */
  29. #include <regx52.h>
  30. #include <intrins.h>
  31. #include <string.h>
  32. #define SIZE 12
  33. sbit Led = P2^0;
  34. sbit Led1= P2^7;
  35. code char LJWL []="AT+CWJAP=\"iPhone\",\"00000000\"\r\n";
  36. code char LJFWQ[]="AT+CIPSTART=\"TCP\",\"169.254.165.190\",8880\r\n";
  37. char TC []="AT+CIPMODE=1\r\n";
  38. char SJFS[]="AT+CIPSEND\r\n";
  39. char buffer[SIZE];
  40. void Delay7000ms()
  41. {
  42. unsigned char i, j, k;
  43. _nop_();
  44. i = 50;
  45. j = 7;
  46. k = 195;
  47. do
  48. {
  49. do
  50. {
  51. while (--k);
  52. } while (--j);
  53. } while (--i);
  54. }
  55. void Delay1000ms()
  56. {
  57. unsigned char i, j, k;
  58. _nop_();
  59. i = 8;
  60. j = 1;
  61. k = 243;
  62. do
  63. {
  64. do
  65. {
  66. while (--k);
  67. } while (--j);
  68. } while (--i);
  69. }
  70. void Uart()
  71. {
  72. PCON = 0x00;
  73. SCON = 0x50;
  74. TMOD = 0x20;
  75. TH1 = 0xFD;
  76. TL1 = 0xFD;
  77. TR1 = 1;
  78. ES = 1;
  79. EA = 1;
  80. }
  81. void SendByt(char Js)
  82. {
  83. SBUF = Js;
  84. while(! TI );
  85. TI = 0;
  86. }
  87. void SendString(char * p)
  88. {
  89. while(*p != '\0')
  90. {
  91. SendByt(*p);
  92. p++;
  93. }
  94. }
  95. void main()
  96. {
  97. Led = 1;
  98. Uart();
  99. Delay1000ms();
  100. SendString(LJWL);
  101. Delay7000ms();
  102. SendString(LJFWQ);
  103. Delay7000ms();
  104. SendString(TC);
  105. Delay1000ms();
  106. SendString(SJFS);
  107. Delay1000ms();
  108. Led = 0;
  109. while(1)
  110. {
  111. SendString("666\r\n");
  112. }
  113. }
  114. void Zd() interrupt 4
  115. {
  116. unsigned char cmd;
  117. static int i = 0;
  118. if(RI == 1)
  119. {
  120. RI = 0;
  121. cmd = SBUF;
  122. if(cmd == 'o' ||cmd == 'c')
  123. {
  124. i = 0;
  125. }
  126. buffer[i++] = cmd;
  127. if(buffer[0] == 'o'&&buffer[3]=='n')
  128. {
  129. Led1 = 0;
  130. memset(buffer, '\0', SIZE);
  131. }
  132. if(buffer[0] == 'c'&& buffer[4]=='e')
  133. {
  134. Led1 = 1;
  135. memset(buffer, '\0', SIZE);
  136. }
  137. if(i == 12)i = 0;
  138. }
  139. }

14.通过4GI模块通 过上位机点亮一个LED

  1. /*
  2. 4G是公网通信不认识:‘局域网’;
  3. 我们可以将内网IP穿透 就是利用花生壳 把内网ip弄成外网可以访问的一个地址端口
  4. 我建立个服务器 通过花生壳把IP打造成外网可以访问的IP 通过AT指令先配置好(4G模块是先配置 重启才能使用)
  5. 单片机接受4G发来的数据 如果检索到跟我设置一样的数据就可以进行点灯操作等。。。
  6. 跟蓝牙一样 优点是突破了地域限制
  7. 1. 打开串口连接4G模块,串口出产默认波特率是115200,可以自行根据用户手册修改
  8. 2. 进入AT指令模式,在串口助手内发送+++(不要勾选发送新行),必须在发送+++指令 3s 内发送其
  9. 他任意 AT 指令,比如AT+CPIN 1 检测到sim卡 0 没有检测到
  10. 3. 观察SIM卡灯是否亮起,AT+ICCID获得SIM卡信息,确认SIM卡安装完好 返回数据:
  11. +OK=89860116838013413419
  12. 检查信号是否正常,通过AT+CSQ指令检查信号值,建议插入信号天线,返回数据:+OK=31
  13. 4. AT+SOCK=TCPC,103.46.128.21,52541 连接socket服务器,
  14. 103.46.128.21是公网IP地址,通过花生壳获得,26532是端口号,参数之间逗号隔开
  15. 5.AT+REBT 重启模块。
  16. 6.AT+UART=9600,NONE none表示没有奇偶校验位 4g默认uart=115200;
  17. 7.AT+LINKSTA 查询 TCP 链接是否已建立链接 返回Connect(TCP 连接)/ Disconnect(TCP 断开)
  18. */
  19. #include <regx52.h>
  20. #include <string.h>
  21. sbit Led = P2^7;
  22. void Uart()
  23. {
  24. PCON = 0x00;
  25. SCON = 0x50;
  26. TMOD = 0x20;
  27. TH1 = 0xFD;
  28. TL1 = 0xFD;
  29. TR1 = 1;
  30. ES = 1;
  31. EA = 1;
  32. }
  33. void main()
  34. {
  35. Led = 1;
  36. Uart();
  37. while(1);
  38. }
  39. void Zd() interrupt 4
  40. {
  41. char cmd;
  42. if(RI == 1)
  43. {
  44. RI = 0;
  45. cmd = SBUF;
  46. if(cmd == 'o')
  47. {
  48. Led = 0;
  49. }
  50. if(cmd == 'c')
  51. {
  52. Led = 1;
  53. }
  54. }
  55. }

 15.Lcd1602详解

RS 为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器
R/W 为读写信号线,高电平时进行读操作,低电平时进行写操作,当 RS 为低电平 R/W 为高电平时可以读忙信号。

  1. #include <regx52.h>
  2. #include <intrins.h>
  3. #define buffer P0
  4. sbit RS = P2^6;
  5. sbit RW = P2^5;
  6. sbit EN = P2^7;
  7. void Read_Busy()
  8. {
  9. char flag = 0x80;
  10. buffer = 0x80;
  11. while(flag & 0x80)
  12. {
  13. RS = 0;
  14. RW = 1;
  15. EN = 0;
  16. _nop_();
  17. EN = 1;
  18. _nop_();
  19. _nop_();
  20. flag = buffer;
  21. EN = 0;
  22. _nop_();
  23. }
  24. }
  25. void Write_Cmd(char cmd)
  26. {
  27. Read_Busy();
  28. RS = 0;
  29. RW = 0;
  30. EN = 0;
  31. _nop_();
  32. buffer = cmd;
  33. _nop_();
  34. EN = 1;
  35. _nop_();
  36. _nop_();
  37. EN = 0;
  38. _nop_();
  39. }
  40. void Write_Data(char Data)
  41. {
  42. Read_Busy();
  43. RW = 0;
  44. RS = 1;
  45. EN = 0;
  46. _nop_();
  47. buffer = Data;
  48. _nop_();
  49. EN = 1;
  50. _nop_();
  51. _nop_();
  52. EN = 0;
  53. _nop_();
  54. }
  55. void Delay5ms() //@12.000MHz
  56. {
  57. unsigned char i, j;
  58. i = 10;
  59. j = 183;
  60. do
  61. {
  62. while (--j);
  63. } while (--i);
  64. }
  65. void Delay15ms() //@12.000MHz
  66. {
  67. unsigned char i, j;
  68. i = 30;
  69. j = 43;
  70. do
  71. {
  72. while (--j);
  73. } while (--i);
  74. }
  75. void LCD1602_Init()
  76. {
  77. //1)延时 15ms
  78. Delay15ms();
  79. //2)写指令 38H(不检测忙信号)
  80. Write_Cmd(0x38);
  81. //3)延时 5ms
  82. Delay5ms();
  83. //4)以后每次写指令,读/写数据操作均需要检测忙信号
  84. //5)写指令 38H:显示模式设置
  85. Write_Cmd(0x38);
  86. //6)写指令 08H:显示关闭
  87. Write_Cmd(0x08);
  88. //7)写指令 01H:显示清屏
  89. Write_Cmd(0x01);
  90. //8)写指令 06H:显示光标移动设置
  91. Write_Cmd(0x06);
  92. //9)写指令 0CH:显示开及光标设置}
  93. Write_Cmd(0x0c);
  94. }
  95. void Data_Show(char hang,char lie,char *p)
  96. {
  97. switch(hang)
  98. {
  99. case 1:
  100. Write_Cmd(0x80 + lie);
  101. while(*p != '\0')
  102. {
  103. Write_Data(*p);
  104. p++;
  105. }
  106. case 2:
  107. Write_Cmd(0x80 + 0x40 + lie);
  108. while(*p != '\0')
  109. {
  110. Write_Data(*p);
  111. p++;
  112. }
  113. }
  114. }
  115. void main()
  116. {
  117. LCD1602_Init();
  118. while(1)
  119. {
  120. Data_Show(1,6,"NO.1");
  121. Data_Show(2,4,"iverson!");
  122. }
  123. //Write_Cmd(0x80);
  124. //Write_Data('a');
  125. }

 16.DTH11温湿度详解

 

  1. #include <regx52.h>
  2. #include <intrins.h>
  3. sbit Led = P2^0;
  4. sbit Dht = P0^0;
  5. char Data[5];
  6. void Uart()
  7. {
  8. PCON = 0x00;
  9. SCON = 0x50;
  10. TMOD = 0x20;
  11. TH1 = 0xFD;
  12. TL1 = 0xFD;
  13. TR1 = 1;
  14. }
  15. void SendByte(char Js)
  16. {
  17. SBUF = Js;
  18. while(!TI);
  19. TI = 0;
  20. }
  21. void SendString(char *p)
  22. {
  23. while(*p != '\0')
  24. {
  25. SendByte(*p);
  26. p++;
  27. }
  28. }
  29. void Delay30us()
  30. {
  31. unsigned char i;
  32. i = 11;
  33. while (--i);
  34. }
  35. void Delay40us()
  36. {
  37. unsigned char i;
  38. _nop_();
  39. i = 15;
  40. while (--i);
  41. }
  42. void Dht_Start()
  43. {
  44. Dht = 1;
  45. Dht = 0;
  46. Delay30us();
  47. Dht = 1;
  48. while(Dht);
  49. while(!Dht);
  50. while(Dht);
  51. }
  52. void Read_Dht()
  53. {
  54. int i;
  55. int j;
  56. char tmp;
  57. char flag;
  58. Dht_Start();
  59. for(i = 0;i < 5;++i)
  60. {
  61. for(j = 0;j < 8;++j)
  62. {
  63. while(!Dht);
  64. Delay40us();
  65. if(Dht == 1)
  66. {
  67. flag = 1;
  68. while(Dht);
  69. }
  70. else
  71. {
  72. flag = 0;
  73. }
  74. tmp = tmp << 1;
  75. tmp = flag | tmp;
  76. }
  77. Data[i] = tmp;
  78. }
  79. }
  80. void Delay500ms()
  81. {
  82. unsigned char i, j, k;
  83. _nop_();
  84. i = 4;
  85. j = 129;
  86. k = 119;
  87. do
  88. {
  89. do
  90. {
  91. while (--k);
  92. } while (--j);
  93. } while (--i);
  94. }
  95. void main()
  96. {
  97. Uart();
  98. while( 1 )
  99. {
  100. Delay500ms();
  101. Read_Dht();
  102. SendString("H:");
  103. SendByte(Data[0] / 10 +0x30); //0x30 - 0x390 - 9的ascll码
  104. SendByte(Data[0] % 10 + 0x30);//这样就可以把对应的字符变成ascll输出
  105. SendByte('.');
  106. SendByte(Data[1] / 10 +0x30);
  107. SendByte(Data[1] % 10 + 0x30);
  108. SendString("\r\n");
  109. SendString("T:");
  110. SendByte(Data[2] / 10 +0x30);
  111. SendByte(Data[2] % 10 + 0x30);
  112. SendByte('.');
  113. SendByte(Data[3] / 10 +0x30);
  114. SendByte(Data[3] % 10 + 0x30);
  115. SendString("\r\n");
  116. }
  117. }

让dht温湿度数据显示在Lcd1602上面

  1. #include <regx52.h>
  2. #include <intrins.h>
  3. #define buffer P0
  4. /*---------定义LCD1602 & DHT 引脚-----------*/
  5. sbit dht = P0^0;
  6. sbit RS = P2^6;
  7. sbit RW = P2^5;
  8. sbit EN = P2^7;
  9. /*----------wd&sd用于存放温湿度数据---------*/
  10. char Data[5];
  11. char sd[9];
  12. char wd[9];
  13. /*----------读第7位是不是高电平-------------*/
  14. void Read_Busy()
  15. {
  16. char flag = 0x80;
  17. buffer = 0x80;
  18. while(flag & 0x80)
  19. {
  20. RS = 0;
  21. RW = 1;
  22. EN = 0;
  23. _nop_();
  24. EN = 1;
  25. _nop_();
  26. _nop_();
  27. flag = buffer;
  28. EN = 0;
  29. _nop_();
  30. }
  31. }
  32. void Write_Cmd(char cmd)
  33. {
  34. Read_Busy();
  35. RS = 0;
  36. RW = 0;
  37. EN = 0;
  38. _nop_();
  39. buffer = cmd;
  40. _nop_();
  41. EN = 1;
  42. _nop_();
  43. _nop_();
  44. EN = 0;
  45. _nop_();
  46. }
  47. void Write_Data(char Data)
  48. {
  49. Read_Busy();
  50. RW = 0;
  51. RS = 1;
  52. EN = 0;
  53. _nop_();
  54. buffer = Data;
  55. _nop_();
  56. EN = 1;
  57. _nop_();
  58. _nop_();
  59. EN = 0;
  60. _nop_();
  61. }
  62. void Delay5ms() //@12.000MHz
  63. {
  64. unsigned char i, j;
  65. i = 10;
  66. j = 183;
  67. do
  68. {
  69. while (--j);
  70. } while (--i);
  71. }
  72. void Delay15ms() //@12.000MHz
  73. {
  74. unsigned char i, j;
  75. i = 30;
  76. j = 43;
  77. do
  78. {
  79. while (--j);
  80. } while (--i);
  81. }
  82. void LCD1602_Init()
  83. {
  84. //1)延时 15ms
  85. Delay15ms();
  86. //2)写指令 38H(不检测忙信号)
  87. Write_Cmd(0x38);
  88. //3)延时 5ms
  89. Delay5ms();
  90. //4)以后每次写指令,读/写数据操作均需要检测忙信号
  91. //5)写指令 38H:显示模式设置
  92. Write_Cmd(0x38);
  93. //6)写指令 08H:显示关闭
  94. Write_Cmd(0x08);
  95. //7)写指令 01H:显示清屏
  96. Write_Cmd(0x01);
  97. //8)写指令 06H:显示光标移动设置
  98. Write_Cmd(0x06);
  99. //9)写指令 0CH:显示开及光标设置}
  100. Write_Cmd(0x0c);
  101. }
  102. void Data_Show(char hang,char lie,char *p)
  103. {
  104. switch(hang)
  105. {
  106. case 1:
  107. Write_Cmd(0x80 + lie);
  108. while(*p != '\0')
  109. {
  110. Write_Data(*p);
  111. p++;
  112. }
  113. case 2:
  114. Write_Cmd(0x80 + 0x40 + lie);
  115. while(*p != '\0')
  116. {
  117. Write_Data(*p);
  118. p++;
  119. }
  120. }
  121. }
  122. void Uart()
  123. {
  124. PCON = 0x00;
  125. SCON = 0x50;
  126. TMOD = 0x20;
  127. TH1 = 0xFD;
  128. TL1 = 0xFD;
  129. TR1 = 1;
  130. }
  131. void SendByte(char Js)
  132. {
  133. SBUF = Js;
  134. while(!TI);
  135. TI = 0;
  136. }
  137. void SendString(char *p)
  138. {
  139. while(*p != '\0')
  140. {
  141. SendByte(*p);
  142. p++;
  143. }
  144. }
  145. void Delay30us()
  146. {
  147. unsigned char i;
  148. i = 11;
  149. while (--i);
  150. }
  151. void Delay40us()
  152. {
  153. unsigned char i;
  154. _nop_();
  155. i = 15;
  156. while (--i);
  157. }
  158. void Dht_Start()
  159. {
  160. dht = 1;
  161. dht = 0;
  162. Delay30us();
  163. dht = 1;
  164. while(dht);
  165. while(!dht);
  166. while(dht);
  167. }
  168. void Read_Dht()
  169. {
  170. int i;
  171. int j;
  172. char tmp;
  173. char flag;
  174. Dht_Start();
  175. for(i = 0;i < 5;++i)
  176. {
  177. for(j = 0;j < 8;++j)
  178. {
  179. while(!dht);
  180. Delay40us();
  181. if(dht == 1)
  182. {
  183. flag = 1;
  184. while(dht);
  185. }
  186. else
  187. {
  188. flag = 0;
  189. }
  190. tmp = tmp << 1;
  191. tmp = flag | tmp;
  192. }
  193. Data[i] = tmp;
  194. }
  195. }
  196. void Put_Data()
  197. {
  198. sd[0] = 's';
  199. sd[1] = 'd';
  200. sd[2] = ':';
  201. sd[3] = Data[0] /10 + 0x30;
  202. sd[4] = Data[0] %10 + 0x30;
  203. sd[5] = '.';
  204. sd[6] = Data[1] /10 + 0x30;
  205. sd[7] = Data[1] %10 + 0x30;
  206. sd[8] = '\0';
  207. wd[0] = 'w';
  208. wd[1] = 'd';
  209. wd[2] = ':';
  210. wd[3] = Data[2] /10 + 0x30;
  211. wd[4] = Data[2] %10 + 0x30;
  212. wd[5] = '.';
  213. wd[6] = Data[3] /10 + 0x30;
  214. wd[7] = Data[3] %10 + 0x30;
  215. wd[8] = '\0';
  216. }
  217. void Delay1000ms() //@11.0592MHz
  218. {
  219. unsigned char i, j, k;
  220. _nop_();
  221. i = 8;
  222. j = 1;
  223. k = 243;
  224. do
  225. {
  226. do
  227. {
  228. while (--k);
  229. } while (--j);
  230. } while (--i);
  231. }
  232. void main()
  233. {
  234. Uart();
  235. Delay1000ms();
  236. LCD1602_Init();
  237. while(1)
  238. {
  239. Delay1000ms();
  240. Read_Dht();
  241. Put_Data();
  242. Delay1000ms();
  243. Delay1000ms();
  244. SendString(wd);
  245. SendString("\r\n");
  246. SendString(sd);
  247. SendString("\r\n");
  248. Data_Show(1,0,wd);
  249. Data_Show(2,0,sd);
  250. }
  251. }

 17.IIC_OLED详解

  1. /*
  2. 代码太多,需要的可以加我qq:2652408527
  3. */
  4. #include <regx52.h>
  5. #include <intrins.h>
  6. #include "oled.h"
  7. #include "oled_ziku.h"
  8. #include "dht.h"
  9. sbit SDA = P0^0;
  10. sbit SCL = P0^1;
  11. sbit dht = P0^2;
  12. extern char Data[5];
  13. extern char sd[9];
  14. extern char wd[9];
  15. void main()
  16. {
  17. Oled_INIT();
  18. Oled_Write_Cmd(0x20);
  19. Oled_Write_Cmd(0x02);//选择页寻址
  20. Oled_Clear();//清屏
  21. while(1)
  22. {
  23. Oled_Show_Str(1,0,"Li zhen");
  24. Oled_Show_Str(2,0,"I LOVE YOU");
  25. Oled_Show_Str(2,80,"!");
  26. }
  27. }

  1. /*
  2. 部分代码,需要的可以加我QQ:2652408527
  3. */
  4. #include <regx52.h>
  5. #include <intrins.h>
  6. #include "oled.h"
  7. #include "oled_ziku.h"
  8. #include "dht.h"
  9. sbit SDA = P0^0;
  10. sbit SCL = P0^1;
  11. sbit dht = P0^2;
  12. extern char Data[5];
  13. extern char sd[9];
  14. extern char wd[9];
  15. char command[5];
  16. void UART_Init()
  17. {
  18. PCON = 0x00;
  19. SCON = 0x50;
  20. TMOD = 0x20;
  21. TH1 = 0xFD;
  22. TL1 = 0xFD;
  23. TR1 = 1;
  24. ES = 1;
  25. EA = 1;
  26. }
  27. void main()
  28. {
  29. UART_Init();
  30. Delay1000ms();
  31. Oled_INIT();
  32. Oled_Write_Cmd(0x20);
  33. Oled_Write_Cmd(0x02);//选择页寻址
  34. Oled_Clear();//清屏
  35. while(1)
  36. {
  37. Read_Dht();
  38. Put_Data();
  39. Oled_Show_Str(4,40,"Li jian hua");
  40. Delay1000ms();
  41. }
  42. }
  43. void zd() interrupt 4
  44. {
  45. static i = 0;
  46. if(RI == 1)
  47. {
  48. RI = 0;
  49. command[i] = SBUF;
  50. i++;
  51. if(command[0]=='o'&&command[1]=='p'&&command[2]=='e'&&command[3]=='n')
  52. {
  53. Oled_Show_Str(1,0,wd);
  54. Oled_Show_Str(2,0,sd);
  55. }
  56. if(command[0]=='c'&&command[1]=='l'&&command[2]=='o'&&command[3]=='s')
  57. {
  58. Oled_Show_Str(1,0," ");
  59. Oled_Show_Str(2,0," ");
  60. }
  61. }
  62. }

 18.四驱小车

由于没有循迹模块,我直接写了一个可以上下左右的小车代码

  1. #include <REGX52.H>
  2. #include "dianji.h"
  3. void UART_Init()
  4. {
  5. PCON = 0x00;
  6. SCON = 0x50;
  7. TMOD = 0x20;
  8. TH1 = 0xFD;
  9. TL1 = 0xFD;
  10. TR1 = 1;
  11. ES = 1;
  12. EA = 1;
  13. }
  14. void zd() interrupt 4
  15. {
  16. if(RI == 1)
  17. {
  18. RI = 0;
  19. if(SBUF == 'a')
  20. {
  21. Dianji_Left1Ward_Init();
  22. Dianji_Left2Ward_Init();
  23. Dianji_Right1Ward_Init();
  24. Dianji_Right2Ward_Init();
  25. }
  26. if(SBUF == 'b')
  27. {
  28. Dianji_Left1Back_Init();
  29. Dianji_Left2Back_Init();
  30. Dianji_Right1Back_Init();
  31. Dianji_Right2Back_Init();
  32. }
  33. if(SBUF == 'e')
  34. {
  35. 7 Stop();
  36. }
  37. }
  38. }

 

 总结

感谢各位的观看,需要其中代码的兄弟可以私聊我。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/534445
推荐阅读
相关标签
  

闽ICP备14008679号