收藏官网首页
楼主: 孤独的蛇

【MEGA64+ESP8266】之智能家居

7

主题

44

帖子

116

积分

注册会员

Rank: 2

积分
116
13#
 楼主| 发表于 2016-8-17 20:55:35 | 只看该作者
校园创客福利
【六、PWM输出】RGB调光、马达控制、调光PWM信号输出
本次设计中的PWM输出5路,其中1路+PG4被用于直流马达的控制,3路用于RGB调光,1路用于自动调光,1路调光PWM输出。
MEGA64一共有4个定时器,其中T0、T2定时器是8位定时器,一共可输出2路PWM信号,但是T0用于红外发射的38KHz载波输出,为保证载波输出精准,故不使用其产生PWM信号;T1、T3定时器是16位定时器,一共可输出6路PWM信号,但这里只使用了5路PWM输出。
下面,看看PWM输出的定时器初始化:
  1. //PWM寄存器设置初始化
  2. /*
  3. T0:PWM输出,红外发射38KHz的方波计时器,2.89351us溢出中断一次
  4. T1:PWM_A输出,PWM_B输出,此处不用PWM_C,如果需要再进行编程,可以转移到其它端口进行操作 2路独立的PWM信号输出,调光
  5. T2:PWM输出,电机PWM控制,溢出中断进行转向控制
  6. T3:3路PWM输出,进行RGB灯的控制
  7. */
  8. void PWM_Ini()
  9. {
  10.         /*IO端口设置,其中PWM2 为电机PWM控制,PWM1A/B/C 为RGB_LED灯亮度控制,PWM3A/B/C为三路LED灯亮度控制*/
  11.         DDRB |= ( _BV(P4) | _BV(P5) | _BV(P6) | _BV(P7) );//设置PB4/PB5/PB6/PB7为输出,分别为PWM0,PWM1A,PWM1B,PWM1C
  12.         DDRE |= ( _BV(P3) | _BV(P4) | _BV(P5) );//设置PE3/PE4/PE5为输出,分别为PWM3A,PWM3B,PWM3C
  13.         DDRG |= _BV(P4);//PG4作为电机控制的另外一个引脚,一个引脚为PWM2 OC2(PB7)
  14.         PORTB |= ( _BV(P4) | _BV(P5) | _BV(P6) | _BV(P7) );//上拉
  15.         PORTE |= ( _BV(P3) | _BV(P4) | _BV(P5) );
  16.         PORTG |= _BV(P4);
  17.         TCCR0 |= ( _BV(COM00) | _BV(WGM01) | _BV(CS01) );//CTC模式,比较匹配时取反,8分频,IR发送38KHz
  18.         /*  TC1的设置在ICP1_Ini()里边设置了部分 8位快速PWM模式,256分频 */
  19.         TCCR1A |= ( _BV(COM1A1) | _BV(COM1B1) );//比较匹配时清零OCnA/OCnB/OCnC,在 TOP 时置位OCnA/OCnB/OCnC OC1C未连接
  20.         TCCR2 |= ( _BV(COM21) | _BV(WGM21) | _BV(WGM20) | _BV(CS22) | _BV(CS20) );//8位快速PWM 1024分频 OC2输出PWM波形,比较匹配发生时OC2 清零 ,计数到TOP 时OC2 置位
  21.         TCCR3A |= ( _BV(COM3A1) | _BV(COM3B1) |_BV(COM3C1) | _BV(WGM30) );//比较匹配时清零OCnA/OCnB/OCnC,在 TOP 时置位OCnA/OCnB/OCnC, 配合TCCR3B设置8位快速PWM
  22.         TCCR3B |= ( _BV(WGM32) | _BV(CS32) );//8位快速PWM模式,256分频
  23.         TIMSK |= ( _BV(TOIE2) | _BV(TOIE1) | _BV(TICIE1) );//T2溢出中断,T1输入捕捉中断,T1溢出中断
  24. //        ETIMSK |= _BV(TOIE3);//T3溢出中断
  25. }
复制代码
在直流马达的控制中,使用的是LB1836M芯片作为驱动芯片。下面是电路图:

下面是LB1836的控制逻辑表:

这里控制电机转速的原理为:
根据逻辑表中可以知道,当IN1和IN2同时为低电平时,电机的状态是自由转动。
当两个输入引脚同时为低电平时,电机的状态是刹车。
当一个输入引脚被固定拉低,另外一个引脚为高电平时,电机就会转动(正转或反转)。由此,我们令一个引脚为低电平,另外一个引脚为PWM信号,就可以控制电机的转速了。
(PS:为什么我们不用一个引脚高电平,一个PWM信号呢?根据逻辑表可知,当两个输入引脚为高电平时,电机会制动刹车。而PWM信号则是一个高低变化的方波信号,即有低电平也有高电平,那么电机的效果就是:转动,刹车,转动,刹车。。。如此循环,那么电机是转动呢?还是刹车?所以马达表现出来的就是可能不转,也可能非常缓慢的转动。那么如果我们让一个引脚固定低电平,一个引脚PWM时,则会:转动,自由转动,转动,自由转动。。。如此下去,电机的效果就是在转动。)
当我们需要电机正转时,则把IN2拉低,IN1给PWM信号;当我们需要电机反转时,则把IN1拉低,IN2给PWM信号。
下面是定时器2的中断函数,其中:
T2的输出比较中断函数主要的作用就是:当我们的PWM信号不是通过MCU内部连接引脚输出的时候,需要另外的引脚输出时,在比较匹配的时候,把引脚拉低,即PWM信号的低电平 |``````````|__________|``````````|__________
T2溢出中断的作用是:当低电平输出到一定的时间后,就把引脚拉高。即高电平占整个方波周期的多少就是电机转速的快慢。

  1. //定时器2输出比较B中断函数
复制代码
下面的函数是马达控制函数:
  1. /*
  2. 直流马达控制  void Motor_Control(unsigned char speed_val,unsigned char dir)
  3. speed_val: 马达速度,值为0-255,0为最小停止,255为最大
  4. dir: 转动方向,0为正转,否则为反转
  5. */
  6. void Motor_Control(unsigned char speed_val,unsigned char dir)
  7. {
  8.         if(speed_val==0)
  9.         {
  10.                 TCCR2 &=~_BV(COM21);//关闭OC2引脚关联
  11.                 TIMSK &= ~_BV(OCIE2);//关闭输出比较中断
  12.                 //TIMSK &= ~_BV(TOIE2);//关闭T2溢出中断
  13.                 pg4_connet = 0;//不关联PG4引脚
  14.                 PORTG &= ~_BV(P4);//拉低
  15.                 PORTB &= ~_BV(P7);//拉低,关闭直流马达,停止
  16.         }
  17.         else
  18.         {
  19.                 OCR2 = speed_val;//设置PWM2为转速值
  20.                 //TIMSK |= _BV(TOIE2);//开启T2溢出中断
  21.                 if(dir==1)//如果方向为反转
  22.                 {
  23.                
  24.                         TCCR2 |=_BV(COM21);//开启OC2引脚关联
  25.                         TIMSK &= ~_BV(OCIE2);//关闭输出比较中断
  26.                         PORTG &= ~_BV(P4);
  27.                         pg4_connet = 0;//不关联PG4引脚
  28.                 }
  29.                 else
  30.                 {
  31.                         TCCR2 &=~_BV(COM21);//关闭OC2引脚关联
  32.                         PORTB &= ~_BV(P7);
  33.                         TIMSK |= _BV(OCIE2);//开启输出比较中断
  34.                         TIMSK |= _BV(TOIE2);//开启T2溢出中断
  35.                         PORTG |= _BV(P4);
  36.                         pg4_connet = 1;//关联PG4引脚
  37.                        
  38.                 }
  39.         }
  40. }
复制代码


PWM调光信号的输出:
  1. /*  PWM信号输出 void PWM_OUT(unsigned char num,unsigned char val)
  2. 输入参数1:unsigned char num 哪一路PWM信号。1:OC1A第一路PWM 2:OC1B第二路PWM 3:OC3A(RGB中的R) 4:OC3B(RGB中的G) 5:OC3C(RGB中的B)
  3. 输入参数2:unsigned char val PWM信号值
  4. */
  5. void PWM_OUT(unsigned char num,unsigned char val)
  6. {
  7.         switch(num)
  8.         {
  9.                 case 1://OC1A PB5 PWM1
  10.                         if(val == 0)//如果PWM值为0,即关闭,则直接把相应的管脚设为0
  11.                         {
  12.                                 TCCR1A &=~_BV(COM1A1);//关闭OC1A引脚关联
  13.                                 //TIMSK &= ~_BV(OCIE1A);//关闭输出比较A中断
  14.                                 PORTB &=~_BV(P5);//输出低电平
  15.                         }
  16.                         else
  17.                         {
  18.                                 OCR1A = val;
  19.                                 TCCR1A |= _BV(COM1A1);//打开OC1A引脚关联
  20.                                 //TIMSK &= ~_BV(OCIE1A);//关闭输出比较A中断
  21.                         }
  22.                         break;
  23.                 case 2://OC1B PB6 PWM2
  24.                         if(val == 0)//如果PWM值为0,即关闭,则直接把相应的管脚设为0
  25.                         {
  26.                                 TCCR1A &=~_BV(COM1B1);//关闭OC1B引脚关联
  27.                                 //TIMSK &= ~_BV(OCIE1B);//关闭输出比较B中断
  28.                                 PORTB &=~_BV(P6);//输出低电平
  29.                         }
  30.                         else
  31.                         {
  32.                                 OCR1B = val;
  33.                                 TCCR1A |= _BV(COM1B1);//打开OC1B引脚关联
  34.                                 //TIMSK &= ~_BV(OCIE1B);//关闭输出比较B中断
  35.                         }
  36.                         break;
  37.                 case 3://OC3A PE3 R
  38.                         if(val == 0)//如果PWM值为0,即关闭,则直接把相应的管脚设为0
  39.                         {
  40.                                 TCCR3A &=~_BV(COM3A1);//关闭OC3A引脚关联
  41.                                 //TIMSK &= ~_BV(OCIE3A);//关闭输出比较A中断
  42.                                 PORTE &=~_BV(P3);//输出低电平
  43.                         }
  44.                         else
  45.                         {
  46.                                 OCR3A = val;
  47.                                 TCCR3A |= _BV(COM3A1);//打开OC3A引脚关联
  48.                                 //TIMSK &= ~_BV(OCIE3A);//关闭输出比较A中断
  49.                         }
  50.                         break;
  51.                 case 4://OC3B PE4 G
  52.                         if(val == 0)//如果PWM值为0,即关闭,则直接把相应的管脚设为0
  53.                         {
  54.                                 TCCR3A &=~_BV(COM3B1);//关闭OC3B引脚关联
  55.                                 //TIMSK &= ~_BV(OCIE3B);//关闭输出比较A中断
  56.                                 PORTE &=~_BV(P4);//输出低电平
  57.                         }
  58.                         else
  59.                         {
  60.                                 OCR3B = val;
  61.                                 TCCR3A |= _BV(COM3B1);//打开OC3B引脚关联
  62.                                 //TIMSK &= ~_BV(OCIE3B);//关闭输出比较A中断
  63.                         }
  64.                         break;
  65.                 case 5://OC3C PE5 B
  66.                         if(val == 0)//如果PWM值为0,即关闭,则直接把相应的管脚设为0
  67.                         {
  68.                                 TCCR3A &=~_BV(COM3C1);//关闭OC3C引脚关联
  69.                                 //TIMSK &= ~_BV(OCIE3C);//关闭输出比较A中断
  70.                                 PORTE &=~_BV(P5);//输出低电平
  71.                         }
  72.                         else
  73.                         {
  74.                                 OCR3C = val;
  75.                                 TCCR3A |= _BV(COM3C1);//打开OC3C引脚关联
  76.                                 //TIMSK &= ~_BV(OCIE3C);//关闭输出比较A中断
  77.                         }
  78.                         break;
  79.                 default:break;
  80.         }
  81. }
复制代码




7

主题

44

帖子

116

积分

注册会员

Rank: 2

积分
116
12#
 楼主| 发表于 2016-8-17 17:43:18 | 只看该作者
【程序中使用到的一个头文件】这个头文件是在网上看到的,稍作修改后使用。在此谢过原作者,让我们轻松实现AVR单片机的位操作!
下面是头文件的部分内容,由于字数限制,所以不能完全写上。需要源文件的,请点击→→这里←← (  访问密码 fa59  )
  1. /*******************************************
  2. *        源文件作用:        AVR GCC下的ATMEMGA64的I/O位域定义方便位操作        *                                                                                                *
  3. *        使用方法:                方法1:#define LED BITFIELD(PORTB_BIT).bit0        *
  4. *                                        方法2:#define LED PORTB_0                                         *
  5. *                                        (推荐使用方法2更直观如要LED置1则:LED = 1;)        *
  6. *        版本:                        Ver:0.1                                                                                *
  7. *        更新日期:                2009-01-13                                                                        *
  8. *        作者:                        Zeng                                                                                *
  9. *        支持文件:                无                                                                                        *
  10. *******************************************/
  11. #ifndef        _M164_BIT_OPERATION_H_
  12. #define _M128_BIT_OPERATION_H_

  13. //定义一个带参的宏代替位域结构体方便使用
  14. #define BITFIELD(addr) (*((volatile bit_field *)(addr)))
  15. //位域定义结构体
  16. typedef struct _bit_struct
  17. {
  18.         unsigned Bit0:1;
  19.         unsigned Bit1:1;
  20.         unsigned Bit2:1;
  21.         unsigned Bit3:1;
  22.         unsigned Bit4:1;
  23.         unsigned Bit5:1;
  24.         unsigned Bit6:1;
  25.         unsigned Bit7:1;
  26. }bit_field;

  27. // I/O PORT地址是在GCC头文件基础上加了0x20的  
  28. #define PORTA_BIT  0x3b
  29. #define PORTB_BIT  0x38
  30. #define PORTC_BIT  0x35
  31. #define PORTD_BIT  0x32
  32. #define PORTE_BIT  0x23
  33. #define PORTF_BIT  0x62
  34. #define PORTG_BIT  0x65

  35. // I/O DDR地址是在GCC头文件基础上加了0x20的
  36. #define DDRA_BIT  0x3A
  37. #define DDRB_BIT  0x37
  38. #define DDRC_BIT  0x34
  39. #define DDRD_BIT  0x31
  40. #define DDRE_BIT  0x22
  41. #define DDRF_BIT  0x61
  42. #define DDRG_BIT  0x64

  43. // I/O PIN地址是在GCC头文件基础上加了0x20的
  44. #define PINA_BIT  0x39
  45. #define PINB_BIT  0x36
  46. #define PINC_BIT  0x33
  47. #define PIND_BIT  0x30
  48. #define PINE_BIT  0x21
  49. #define PINF_BIT  0x20
  50. #define PING_BIT  0x63


  51. //进行位域定义后的DDRA可按位直接操作
  52. #define DDRA_0     ((*(volatile bit_field *)(DDRA_BIT)).Bit0)
  53. #define DDRA_1     ((*(volatile bit_field *)(DDRA_BIT)).Bit1)
  54. #define DDRA_2     ((*(volatile bit_field *)(DDRA_BIT)).Bit2)
  55. #define DDRA_3     ((*(volatile bit_field *)(DDRA_BIT)).Bit3)
  56. #define DDRA_4     ((*(volatile bit_field *)(DDRA_BIT)).Bit4)
  57. #define DDRA_5     ((*(volatile bit_field *)(DDRA_BIT)).Bit5)
  58. #define DDRA_6     ((*(volatile bit_field *)(DDRA_BIT)).Bit6)
  59. #define DDRA_7     ((*(volatile bit_field *)(DDRA_BIT)).Bit7)
  60. //进行位域定义后的DDRB可按位直接操作
  61. #define DDRB_0     ((*(volatile bit_field *)(DDRB_BIT)).Bit0)
  62. #define DDRB_1     ((*(volatile bit_field *)(DDRB_BIT)).Bit1)
  63. #define DDRB_2     ((*(volatile bit_field *)(DDRB_BIT)).Bit2)
  64. #define DDRB_3     ((*(volatile bit_field *)(DDRB_BIT)).Bit3)
  65. #define DDRB_4     ((*(volatile bit_field *)(DDRB_BIT)).Bit4)
  66. #define DDRB_5     ((*(volatile bit_field *)(DDRB_BIT)).Bit5)
  67. #define DDRB_6     ((*(volatile bit_field *)(DDRB_BIT)).Bit6)
  68. #define DDRB_7     ((*(volatile bit_field *)(DDRB_BIT)).Bit7)
  69. //进行位域定义后的DDRC可按位直接操作
  70. #define DDRC_0     ((*(volatile bit_field *)(DDRC_BIT)).Bit0)
  71. #define DDRC_1     ((*(volatile bit_field *)(DDRC_BIT)).Bit1)
  72. #define DDRC_2     ((*(volatile bit_field *)(DDRC_BIT)).Bit2)
  73. #define DDRC_3     ((*(volatile bit_field *)(DDRC_BIT)).Bit3)
  74. #define DDRC_4     ((*(volatile bit_field *)(DDRC_BIT)).Bit4)
  75. #define DDRC_5     ((*(volatile bit_field *)(DDRC_BIT)).Bit5)
  76. #define DDRC_6     ((*(volatile bit_field *)(DDRC_BIT)).Bit6)
  77. #define DDRC_7     ((*(volatile bit_field *)(DDRC_BIT)).Bit7)
  78. //进行位域定义后的DDRD可按位直接操作
  79. #define DDRD_0     ((*(volatile bit_field *)(DDRD_BIT)).Bit0)
  80. #define DDRD_1     ((*(volatile bit_field *)(DDRD_BIT)).Bit1)
  81. #define DDRD_2     ((*(volatile bit_field *)(DDRD_BIT)).Bit2)
  82. #define DDRD_3     ((*(volatile bit_field *)(DDRD_BIT)).Bit3)
  83. #define DDRD_4     ((*(volatile bit_field *)(DDRD_BIT)).Bit4)
  84. #define DDRD_5     ((*(volatile bit_field *)(DDRD_BIT)).Bit5)
  85. #define DDRD_6     ((*(volatile bit_field *)(DDRD_BIT)).Bit6)
  86. #define DDRD_7     ((*(volatile bit_field *)(DDRD_BIT)).Bit7)
  87. //进行位域定义后的DDRE可按位直接操作
  88. #define DDRE_0     ((*(volatile bit_field *)(DDRE_BIT)).Bit0)
  89. #define DDRE_1     ((*(volatile bit_field *)(DDRE_BIT)).Bit1)
  90. #define DDRE_2     ((*(volatile bit_field *)(DDRE_BIT)).Bit2)
  91. #define DDRE_3     ((*(volatile bit_field *)(DDRE_BIT)).Bit3)
  92. #define DDRE_4     ((*(volatile bit_field *)(DDRE_BIT)).Bit4)
  93. #define DDRE_5     ((*(volatile bit_field *)(DDRE_BIT)).Bit5)
  94. #define DDRE_6     ((*(volatile bit_field *)(DDRE_BIT)).Bit6)
  95. #define DDRE_7     ((*(volatile bit_field *)(DDRE_BIT)).Bit7)
  96. //进行位域定义后的DDRF可按位直接操作
  97. #define DDRF_0     ((*(volatile bit_field *)(DDRF_BIT)).Bit0)
  98. #define DDRF_1     ((*(volatile bit_field *)(DDRF_BIT)).Bit1)
  99. #define DDRF_2     ((*(volatile bit_field *)(DDRF_BIT)).Bit2)
  100. #define DDRF_3     ((*(volatile bit_field *)(DDRF_BIT)).Bit3)
  101. #define DDRF_4     ((*(volatile bit_field *)(DDRF_BIT)).Bit4)
  102. #define DDRF_5     ((*(volatile bit_field *)(DDRF_BIT)).Bit5)
  103. #define DDRF_6     ((*(volatile bit_field *)(DDRF_BIT)).Bit6)
  104. #define DDRF_7     ((*(volatile bit_field *)(DDRF_BIT)).Bit7)
  105. //进行位域定义后的DDRG可按位直接操作
  106. #define DDRG_0     ((*(volatile bit_field *)(DDRG_BIT)).Bit0)
  107. #define DDRG_1     ((*(volatile bit_field *)(DDRG_BIT)).Bit1)
  108. #define DDRG_2     ((*(volatile bit_field *)(DDRG_BIT)).Bit2)
  109. #define DDRG_3     ((*(volatile bit_field *)(DDRG_BIT)).Bit3)
  110. #define DDRG_4     ((*(volatile bit_field *)(DDRG_BIT)).Bit4)
  111. //进行位域定义后的PORTA可按位直接操作
  112. #define PORTA_0     ((*(volatile bit_field *)(PORTA_BIT)).Bit0)
  113. #define PORTA_1     ((*(volatile bit_field *)(PORTA_BIT)).Bit1)
  114. #define PORTA_2     ((*(volatile bit_field *)(PORTA_BIT)).Bit2)
  115. #define PORTA_3     ((*(volatile bit_field *)(PORTA_BIT)).Bit3)
  116. #define PORTA_4     ((*(volatile bit_field *)(PORTA_BIT)).Bit4)
  117. #define PORTA_5     ((*(volatile bit_field *)(PORTA_BIT)).Bit5)
  118. #define PORTA_6     ((*(volatile bit_field *)(PORTA_BIT)).Bit6)
  119. #define PORTA_7     ((*(volatile bit_field *)(PORTA_BIT)).Bit7)
  120. //进行位域定义后的PORTB可按位直接操作
  121. #define PORTB_0     ((*(volatile bit_field *)(PORTB_BIT)).Bit0)
  122. #define PORTB_1     ((*(volatile bit_field *)(PORTB_BIT)).Bit1)
  123. #define PORTB_2     ((*(volatile bit_field *)(PORTB_BIT)).Bit2)
  124. #define PORTB_3     ((*(volatile bit_field *)(PORTB_BIT)).Bit3)
  125. #define PORTB_4     ((*(volatile bit_field *)(PORTB_BIT)).Bit4)
  126. #define PORTB_5     ((*(volatile bit_field *)(PORTB_BIT)).Bit5)
  127. #define PORTB_6     ((*(volatile bit_field *)(PORTB_BIT)).Bit6)
  128. #define PORTB_7     ((*(volatile bit_field *)(PORTB_BIT)).Bit7)
  129. //进行位域定义后的PORTC可按位直接操作
  130. #define PORTC_0     ((*(volatile bit_field *)(PORTC_BIT)).Bit0)
  131. #define PORTC_1     ((*(volatile bit_field *)(PORTC_BIT)).Bit1)
  132. #define PORTC_2     ((*(volatile bit_field *)(PORTC_BIT)).Bit2)
  133. #define PORTC_3     ((*(volatile bit_field *)(PORTC_BIT)).Bit3)
  134. #define PORTC_4     ((*(volatile bit_field *)(PORTC_BIT)).Bit4)
  135. #define PORTC_5     ((*(volatile bit_field *)(PORTC_BIT)).Bit5)
  136. #define PORTC_6     ((*(volatile bit_field *)(PORTC_BIT)).Bit6)
  137. #define PORTC_7     ((*(volatile bit_field *)(PORTC_BIT)).Bit7)
  138. //进行位域定义后的PORTD可按位直接操作
  139. #define PORTD_0     ((*(volatile bit_field *)(PORTD_BIT)).Bit0)
  140. #define PORTD_1     ((*(volatile bit_field *)(PORTD_BIT)).Bit1)
  141. #define PORTD_2     ((*(volatile bit_field *)(PORTD_BIT)).Bit2)
  142. #define PORTD_3     ((*(volatile bit_field *)(PORTD_BIT)).Bit3)
  143. #define PORTD_4     ((*(volatile bit_field *)(PORTD_BIT)).Bit4)
  144. #define PORTD_5     ((*(volatile bit_field *)(PORTD_BIT)).Bit5)
  145. #define PORTD_6     ((*(volatile bit_field *)(PORTD_BIT)).Bit6)
  146. #define PORTD_7     ((*(volatile bit_field *)(PORTD_BIT)).Bit7)
  147. //进行位域定义后的PORTE可按位直接操作
  148. #define PORTE_0     ((*(volatile bit_field *)(PORTE_BIT)).Bit0)
  149. #define PORTE_1     ((*(volatile bit_field *)(PORTE_BIT)).Bit1)
  150. #define PORTE_2     ((*(volatile bit_field *)(PORTE_BIT)).Bit2)
  151. #define PORTE_3     ((*(volatile bit_field *)(PORTE_BIT)).Bit3)
  152. #define PORTE_4     ((*(volatile bit_field *)(PORTE_BIT)).Bit4)
  153. #define PORTE_5     ((*(volatile bit_field *)(PORTE_BIT)).Bit5)
  154. #define PORTE_6     ((*(volatile bit_field *)(PORTE_BIT)).Bit6)
  155. #define PORTE_7     ((*(volatile bit_field *)(PORTE_BIT)).Bit7)

  156. ...这里不是所有内容<span style="line-height: 1.5;">------------------------------------------------------------------------------------</span>
复制代码
将以上代码保存为:“M64_BIT_OPERATION.H”,在主程序中调用
  1. #include "M64_BIT_OPERATION.H"
复制代码
再次感谢作者Zeng!

7

主题

44

帖子

116

积分

注册会员

Rank: 2

积分
116
11#
 楼主| 发表于 2016-8-17 17:34:11 | 只看该作者
【五、音乐MP3控制】
这里使用的是WTV020-SD语音模块(因为手上就有这个模块了。。。有好的模块可以替换掉)
1、产品特征
  
Ø  产品支持外挂最大1G容量的SD卡;
  
Ø  支持播放4Bit ADPCM格式文件;
  
Ø  自动识别语音文件;
  
Ø  可装载6KHz~32KHz、36KHz采样率AD4音频;
  
Ø  可装载6KHz~16KHz采样率WAV音频;
  
Ø  16bitDAC及PWM音频输出;
  
Ø  最多可存放512段语音;
  
Ø  WTV020-SD-20S,WTV020-SD-16P两种模块类型;
  
  
  
  
Ø  支持微型处理器和按键控制;
  
Ø  可以调用任意段落的语音进行播放;
  
Ø  掉电保存操作数据功能;
  
Ø  加载语音无需软件辅助,直接放置语音到SD卡便可;
  
Ø  支持文件组合播放,包括静音组合;
  
Ø  工作电压:DC2.5~3.6V;
  
Ø  静态电流:16uA(不插SD卡)
  
2、产品概述
WTV020-SD模块是一款可重复擦写语音内容的大容量存储类型的语音模块,可外挂最大容量为1GB的SD卡存储器。能加载WAV格式语音和AD4格式语音。
WTV020-SD模块以WTV020SD-20S语音芯片为主控核心,具有MP3控制模式,按键一对一控制模式(3段语音跟5段语音两种),上电循环播放控制模式以及二线串口控制模式。控制模式是在芯片制样时设置的,在操作过程中不能切换各种控制模式,如需要使用哪种模式进行控制,可向我司订做。
MP3控制模式:具有播放/停止,下一曲,上一曲,音量+,音量-等功能。
按键一对一控制模式(3段语音):一个按键对应触发一个语音,具备播放3段语音及调节音量加减的功能,所有按键被默认为脉冲不可重复触发。
按键一对一控制模式(5段语音):具有三种控制方式,⑴、所有按键均为脉冲可重复触发;⑵、所有按键均为播放/停止触发(单曲不循环);⑶、所有按键均为播放/停止(单曲可循环)。
上电循环播放控制模式:上电后,不需要触发任何I/O口,直接自动播放SD卡存储器内的所有语音,并拥有断电记忆点播放功能,当断电后再上电,自动从上次的断电处继续播放语音。具有两种控制方式,⑴、P04拥有脉冲播放/暂停功能;⑵、P05拥有电平播放/暂停功能。
二线串口控制模式:由单片机通过CLK时钟和DI数据线发送数据对WTV020-SD模块进行控制。可随意播放任何一个地址的语音。此状态下,能进行语音组合播放。
语音内容更新直接通过SD卡读卡器在PC上更换。该模块支持FAT文件系统。支持6KHz~32KHz、36KHz采样率的AD4语音和6KHz~16KHz采样率的WAV音频,能自动识别语音采样率以及语音文件格式。

点击这里可以下载此文档手册 (  访问密码 8861 )

  1. //音乐设置
  2. #define STOP 0xffff        //停止播放
  3. #define PLAY 0xfffe        //播放
  4. #define PAUSE 0xfffe        //暂停
  5. #define SINGLE_CYCLE 0xfffd        //单曲循环
  6. #define STOP_CYCLE 0xfffc        //停止循环
  7. #define ALL_CYCLE 0xfffb        //所有循环
  8. #define REST PORTG_2
  9. #define DI PORTG_1
  10. #define CLK PORTG_0
  11. volatile unsigned int voice_buf[8] = {0xfff0,0xfff1,0xfff2,0xfff3,0xfff4,0xfff5,0xfff6,0xfff7};        //音量 0xf0为静音  0xf7 为音量最大
  12. volatile unsigned char voice;
  13. volatile unsigned int song_number;
复制代码
  1. void init_fun()        //初始化模块
  2. {
  3.         voice = 1;        //初始音量设置为3,        0为最小,即静音;        7为最高
  4.    
  5.     song_number = 0;        //第1首歌曲
  6.     REST = 1;
  7.     DI = 1;
  8.     CLK = 1;
  9.     reset_fun();
  10.     delay_ms(300);
  11.     sent_data(voice_buf[voice]);
  12.     sent_data(ALL_CYCLE);
  13. }

  14. void reset_fun()        //复位模块
  15. {
  16.         REST = 0;
  17.         delay_ms(6);
  18.           REST = 1;
  19.         delay_ms(6);
  20. }

  21. void sent_data(uint dat)        //发送数据
  22. {
  23.         unsigned int i;
  24.         uint j;
  25.         for(i=0;i<16;i++)
  26.         {
  27.                 CLK = 0;
  28.                 j = (dat >> (15 - i)) & 0x01;
  29.                 DI = j;
  30.                 delay_ms(2);
  31.                 CLK = 1;
  32.                 delay_ms(2);
  33.         }
  34.         DI = 1;
  35.         CLK = 1;
  36. }
  37. void next_song()        //下一曲
  38. {
  39.         song_number++;
  40.         if(song_number > 0x1ff) song_number = 0x00;
  41.         sent_data(song_number);
  42. }
  43. void pre_song()        //上一曲
  44. {
  45.         if(song_number == 0x00)
  46.         {
  47.                 song_number = 0x200;
  48.         }
  49.         song_number--;
  50.         sent_data(song_number);
  51. }
  52. void voice_up()        //音量加
  53. {
  54.         voice++;
  55.         if(voice >= 7) voice = 7;
  56.         sent_data(voice_buf[voice]);
  57. }

  58. void voice_down()        //音量减
  59. {
  60.         if(voice <= 0) voice = 1;
  61.         voice--;
  62.         sent_data(voice_buf[voice]);
  63. }
  64. void play_song(int song_num)
  65. {
  66.   song_number = song_num;
  67.   if(song_number > 0x1ff) song_number = 0x00;
  68.   sent_data(PLAY);
  69.   sent_data(song_number);
  70. }
复制代码


串口数据处理部分程序
  1. case 0x20://设置music  ok
  2.                                                                 temp1 = ((status1[3] & 0b11100000) >> 5);
  3.                                                                 status[3] = status1[3];
  4.                                                                 status[2] = status1[2];
  5.                                                                 temp2 = (((status1[2] & 0b00000001) << 3) | temp1);
  6.                                                                 if(temp2 != 0)
  7.                                                                 {
  8.                                                                         switch(temp2)
  9.                                                                         {
  10.                                                                                 case 0x01://播放/暂停
  11.                                                                                         sent_data(PLAY);break;
  12.                                                                                 case 0x02://上一曲
  13.                                                                                         pre_song();break;
  14.                                                                                 case 0x03://下一曲
  15.                                                                                         next_song();break;
  16.                                                                                 case 0x04://音量+
  17.                                                                                         voice_up();break;
  18.                                                                                 case 0x05://音量-
  19.                                                                                         voice_down();break;
  20.                                                                                 case 0x06://停止播放
  21.                                                                                         sent_data(STOP);break;
  22.                                                                                 case 0x07://单曲循环
  23.                                                                                         sent_data(SINGLE_CYCLE);break;
  24.                                                                                 case 0x08://所有循环
  25.                                                                                         sent_data(ALL_CYCLE);break;
  26.                                                                                 case 0x09://停止循环
  27.                                                                                         sent_data(STOP_CYCLE);break;
  28.                                                                                 case 0x0a://随机播放一首歌
  29.                                                                                         sent_data(random_fun(0,512));
  30.                                                                                         break;//暂时不设置
  31.                                                                         }
  32.                                                                         status[3] = (status1[3] & 0b00011111);
  33.                                                                         status[2] = (status1[2] & 0b11111110);
  34.                                                                 }
  35.                                                                 break;
复制代码
主函数中音乐相关处理程序:
  1.   //音乐处理
  2.                 if(command_music!=0)
  3.                 {
  4.                         switch(command_music)
  5.                         {
  6.                                 case 0x00:break;//无动作
  7.                                 case 0x01://播放/暂停
  8.                                 sent_data(PLAY);
  9.                                 break;
  10.                                 case 0x02://上一曲
  11.                                 pre_song();
  12.                                 break;
  13.                                 case 0x03://下一曲
  14.                                 next_song();
  15.                                 break;
  16.                                 case 0x04://音量加
  17.                                         voice_up();
  18.                                         break;
  19.                                 case 0x05://音量减
  20.                                         voice_down();
  21.                                         break;
  22.                                 case 0x06://停止
  23.                                         sent_data(STOP);
  24.                                         break;
  25.                                 case 0x07://单曲循环
  26.                                         sent_data(SINGLE_CYCLE);
  27.                                         break;
  28.                                 case 0x08://所有循环
  29.                                         sent_data(ALL_CYCLE);
  30.                                         break;
  31.                                 case 0x09://停止循环
  32.                                         sent_data(STOP_CYCLE);
  33.                                         break;
  34.                                 case 0x0a://随机播放一首歌曲
  35.                                         play_song(random_fun(0,512));
  36.                                         break;
  37.                         }
  38.                 command_music = 0;
  39.                 }
复制代码





7

主题

44

帖子

116

积分

注册会员

Rank: 2

积分
116
10#
 楼主| 发表于 2016-8-17 17:20:16 | 只看该作者
【四、自动收衣服与自动窗帘】的设计
自动窗帘的自动收衣服的原理是一样的,这里就介绍自动窗帘。
自动窗帘的原理是:当系统首次运行或重启后,窗帘会强制先进行回到限位点;当我们给定一个窗帘打开的位置数值时,MCU会计算此时窗帘的位置和欲设定的的位置进行比较,比较结果用来判断是打开还是关闭窗帘。
这里,我使用的演示电机是一个小型直流电机,电机驱动芯片是LB1836M,使用镂空编码盘和红外对管进行位置检测。
通过马达的旋转,经过传输带带动窗帘的运动,马达正转则窗帘打开,马达反转则窗帘关闭。在马达的输出轴上,固定一个编码器码盘,通过红外对管进行马达转动的角度,即是窗帘移动的位置。


首先,程序运行时,先进行初始化:(执行结果是程序运行初始时,窗帘先全部关闭)
  1. //窗帘位置初始化
  2. void curtain_init()
  3. {
  4.         while(PIND_5 == 0)//关闭窗帘,直到窗帘限位开关检测到触碰信号
  5.         {
  6.                 PORTC_0=1;
  7.                 PORTC_1=0;
  8.         }
  9.         PORTC_0=0;
  10.         PORTC_1=0;
  11.         curtain_current_val=100;//设置当前打开位置百分百为100,即全关闭
  12. }
复制代码
初始化完毕后,如果传来调整的命令,则进行窗帘位置调整:
  1. /*
  2. 窗帘位置设置curtainpos_set(unsigned char val)
  3. 输入参数:val 窗帘打开位置百分比
  4. */
  5. void curtainpos_set(unsigned char val)
  6. {
  7.         if( val > curtain_current_val)
  8.         {
  9.                 //关闭窗帘
  10.                 PORTC_0 = 1;
  11.                 PORTC_1 = 0;

  12.         }
  13.         else if(val < curtain_current_val)
  14.         {
  15.                 //打开窗帘
  16.                 PORTC_0 = 0;
  17.                 PORTC_1 = 1;
  18.         }
  19.         else
  20.         {
  21.                 //正好处于设置位置
  22.                 PORTC_0 = 0;
  23.                 PORTC_1 = 0;
  24.         }
  25. }
复制代码
  1. //外部中断0中断函数,对窗帘位置进行监测
  2. ISR(INT0_vect)
  3. {
  4.         if(curtain_dir == 1)//打开窗帘
  5.         {
  6.                 curtain_count++;
  7.                 if(curtain_count >= CURTAIN_MAX)//如果窗帘位置大于最大值时,把位置设置为最大值
  8.                 {
  9.                         curtain_count = CURTAIN_MAX;
  10.                 }
  11.         }
  12.         else
  13.         {
  14.                 curtain_count--;
  15.                 if(curtain_count <= 0)//如果窗帘位置大于最小值时,把位置设置为最小值
  16.                 {
  17.                         curtain_count = 0;
  18.                 }
  19.         }
  20.         curtain_current_val = (unsigned char) (curtain_count / CURTAIN_MAX);//获取窗帘当前打开百分比
  21. }
复制代码
下面是自动收衣服的程序:
  1. //自动收衣服初始化
  2. void dress_init()
  3. {
  4.         while(PIND_6 == 0)//收回衣服,直到衣服限位开关检测到触碰信号
  5.         {
  6.                 PORTC_2=1;
  7.                 PORTC_3=0;
  8.         }
  9.         PORTC_2=0;
  10.         PORTC_3=0;
  11.         dress_current_val=0;//设置当前打开位置百分百为0,即全收回
  12. }

  13. /*
  14. 窗帘位置设置void dresspos_set(unsigned char val)
  15. 输入参数:val 衣服打开位置百分比
  16. */
  17. void dresspos_set(unsigned char val)
  18. {
  19.         if( val > dress_current_val)
  20.         {
  21.                 //关闭窗帘
  22.                 PORTC_2 = 1;
  23.                 PORTC_3 = 0;

  24.         }
  25.         else if(val < dress_current_val)
  26.         {
  27.                 //打开窗帘
  28.                 PORTC_2 = 0;
  29.                 PORTC_3 = 1;
  30.         }
  31.         else
  32.         {
  33.                 //正好处于设置位置
  34.                 PORTC_2 = 0;
  35.                 PORTC_3 = 0;
  36.         }
  37. }
复制代码
  1. //外部中断1中断函数
  2. ISR(INT1_vect)
  3. {
  4.         if(dress_dir == 1)//打开衣服
  5.         {
  6.                 dress_count++;
  7.                 if(dress_count >= DRESS_MAX)//如果自动收衣服位置大于最大值时,把位置设置为最大值
  8.                 {
  9.                         dress_count = DRESS_MAX;
  10.                 }
  11.         }
  12.         else
  13.         {
  14.                 dress_count--;
  15.                 if(dress_count <= 0)//如果自动收衣服位置大于最小值时,把位置设置为最小值
  16.                 {
  17.                         dress_count = 0;
  18.                 }
  19.         }
  20.         dress_current_val = (unsigned char) (curtain_count / CURTAIN_MAX);//获取衣服当前打开百分比

  21. }
复制代码









7

主题

44

帖子

116

积分

注册会员

Rank: 2

积分
116
9#
 楼主| 发表于 2016-8-17 16:38:02 | 只看该作者
汉枫LPB120模块
【三、智能插座】的设计
智能插座和智能开关的原理是一样的,这里就不再阐述。

7

主题

44

帖子

116

积分

注册会员

Rank: 2

积分
116
8#
 楼主| 发表于 2016-8-9 12:24:37 | 只看该作者
MCU



红外发射和接收模块


智能插座模块


智能开关模块


晶振和复位模块


RGB和自动调光模块


按键和指示灯模块


调速风扇和窗帘/自动收衣服电机控制模块




7

主题

44

帖子

116

积分

注册会员

Rank: 2

积分
116
7#
 楼主| 发表于 2016-8-8 23:07:06 | 只看该作者

二、【智能开关】设计

本帖最后由 孤独的蛇 于 2016-8-8 23:31 编辑

首先,智能开关的主要功能是控制用电器的通电与断电,可以通过MCU对继电器进行的操作进行控制。
这里使用到的是MEGA64的PA4/PA5/PA6/PA7口进行4路控制。
欲使用MCU的IO口,首先要对IO口进行配置,这里需要配置成输出模式:
  1. DDRA |= 0b00001111;//将PA4-PA7设置为输出模式
  2. PORTA &= 0b11110000;//将PA4-PA7设置为低电平
复制代码
当MCU上电之后,将PA4-PA7设置为输出模式,并将对应的IO口进行拉低处理,因为这里设计的智能开关的控制是高电平控制的,所有当MCU上电之后进行拉低,防止上电时开关就打开。对于如何控制IO口的高低电平则非常简单:
  1. PORTA |= _BV(4);//让PA4输出高电平
  2. PORTA &=~_BV(4);//让PA4输出低电平
复制代码
当收到远程发送过来的命令时,就可以对智能开关进行控制了。
下面代码中的attr_flags4是“是否设置标志位”中的一字节数据,查看相应的通信协议。
status1数组是存放串口发送过来的数据,status数组则是整个系统中的状态数组。LED1、2、3、4等是智能开关的引脚,CHAZUO1 、2、3、4是智能插座的引脚。
  1. switch(attr_flags4)
  2. {
  3.         case 0x01://设置LED1
  4.                 if(status1[5]==0x01)
  5.                 {
  6.                         LED1 = 1;
  7.                          temp1= status[5];
  8.                          status[5] = (temp1 | 0b00000001);
  9.                  }
  10.                  else
  11.                   {
  12.                            LED1 = 0;
  13.                            temp1= status[5];
  14.                            status[5] = (temp1 & 0b11111110);
  15.                     }
  16.                    break;
  17.          case 0x02://设置LED2
  18.                  if(status1[5]==0x02)
  19.                  {
  20.                        LED2 = 1;
  21.                        temp1= status[5];
  22.                        status[5] = (temp1 | 0b00000010);
  23.                 }
  24.                 else
  25.                 {
  26.                          LED2 = 0;
  27.                          temp1= status[5];
  28.                          status[5] = (temp1 & 0b11111101);
  29.                  }
  30.                  break;
  31.          case 0x04://设置LED3
  32.                  if(status1[5]==0x04)
  33.                  {
  34.                           LED3 = 1;
  35.                           temp1= status[5];
  36.                           status[5] = (temp1 | 0b00000100);
  37.                    }
  38.                    else
  39.                    {
  40.                             LED3 = 0;
  41.                             temp1= status[5];
  42.                             status[5] = (temp1 & 0b11111011);
  43.                     }
  44.                     break;
  45.             case 0x08://设置LED4
  46.                     if(status1[5]==0x08)
  47.                     {
  48.                              LED4 = 1;
  49.                              temp1= status[5];
  50.                              status[5] = (temp1 | 0b00001000);
  51.                       }
  52.                       else
  53.                      {
  54.                               LED4 = 0;
  55.                               temp1= status[5];
  56.                               status[5] = (temp1 & 0b11110111);
  57.                       }
  58.                       break;
  59.               case 0x10://设置JACK1
  60.                       if(status1[5]==0x10)
  61.                       {
  62.                                 CHAZUO1 = 1;
  63.                                  temp1= status[5];
  64.                                  status[5] = (temp1 | 0b00010000);
  65.                         }
  66.                         else
  67.                         {
  68.                                    CHAZUO1 = 0;
  69.                                     temp1 = status[5];
  70.                                     status[5] = (temp1 & 0b11101111);
  71.                           }
  72.                            break;
  73.                   case 0x20://设置JACK2
  74.                           if(status1[5]==0x20)
  75.                           {
  76.                                      CHAZUO2 = 1;
  77.                                       temp1 = status[5];
  78.                                        status[5] = (temp1 | 0b00100000);
  79.                             }
  80.                             else
  81.                             {
  82.                                         CHAZUO2 = 0;
  83.                                         temp1 = status[5];
  84.                                         status[5] = (temp1 & 0b11011111);
  85.                               }
  86.                       case 0x40://设置JACK3
  87.                               if(status1[5]==0x40)
  88.                               {
  89.                                           CHAZUO3 = 1;
  90.                                            temp1 = status[5];
  91.                                            status[5] = (temp1 | 0b01000000);
  92.                                 }
  93.                                 else
  94.                                 {
  95.                                            CHAZUO3 = 0;
  96.                                             temp1 = status[5];
  97.                                              status[5] = (temp1 & 0b10111111);
  98.                                  }
  99.                        case 0x80://设置JACK4
  100.                                  if(status1[5]==0x80)
  101.                                  {
  102.                                           CHAZUO4 = 1;
  103.                                           temp1 = status[5];
  104.                                            status[5] = (temp1 | 0b10000000);
  105.                                    }
  106.                                    else
  107.                                     {
  108.                                              CHAZUO4 = 0;
  109.                                                temp1 = status[5];
  110.                                                 status[5] = (temp1 & 0b01111111);
  111.                                       }
  112. }
复制代码



【PS】本次设计是对于远程进行控制的,没有进行直接硬件操作控制,如果需要直接硬件操作控制,其实也很简单,直接再加上一个按键进行控制。
思路如下:
加入一个按键,比如接到PA5,智能开关输出接PA4,在进行IO配置时,把PA5设置为输入,PA4设置为输出。在程序中监控PA5是否被按下即可进行控制,同时也可以进行远程控制,这样才打到真正智能家居的目的。



7

主题

44

帖子

116

积分

注册会员

Rank: 2

积分
116
6#
 楼主| 发表于 2016-8-8 22:57:18 | 只看该作者

一、数据点的设置

本次设计中暂时使用35个数据点进行监测,分别是:
  • 名称:LED灯开关1标识名:LED1读写类型:可写类型:布尔值





  • 名称:LED灯开关2标识名:LED2读写类型:可写类型:布尔值



  • 名称:LED灯开关3标识名:LED3读写类型:可写类型:布尔值



  • 名称:LED灯开关4标识名:LED4读写类型:可写类型:布尔值



  • 名称:插座开关1标识名:JACK1读写类型:可写类型:布尔值



  • 名称:插座开关2标识名:JACK2读写类型:可写类型:布尔值



  • 名称:插座开关3标识名:JACK3读写类型:可写类型:布尔值



  • 名称:插座开关4标识名:JACK4读写类型:可写类型:布尔值



  • 名称:空气温度标识名:temperature读写类型:只读类型:数值
    数据范围:0 - 50分辨率:1增量:0



  • 名称:空气湿度标识名:humidity读写类型:只读类型:数值
    数据范围:20 - 90分辨率:1增量:20



  • 名称:红光亮度标识名:R读写类型:可写类型:数值
    数据范围:0 - 255分辨率:1增量:0



  • 名称:绿光亮度标识名:G读写类型:可写类型:数值
    数据范围:0 - 255分辨率:1增量:0



  • 名称:蓝光亮度标识名:B读写类型:可写类型:数值
    数据范围:0 - 255分辨率:1增量:0



  • 名称:PWM1标识名:PWM1读写类型:可写类型:数值
    数据范围:0 - 255分辨率:1增量:0



  • 名称:PWM2标识名:PWM2读写类型:可写类型:数值
    数据范围:0 - 255分辨率:1增量:0



  • 名称:马达转动方向标识名:motodir读写类型:可写类型:布尔值



  • 名称:马达转动速度标识名:motospeed读写类型:可写类型:数值
    数据范围:0 - 255分辨率:1增量:0



  • 名称:火焰传感器值标识名:fireval读写类型:只读类型:数值
    数据范围:0 - 1023分辨率:1增量:0



  • 名称:可燃气体传感器值标识名:gasval读写类型:只读类型:数值
    数据范围:0 - 1023分辨率:1增量:0



  • 名称:雨滴传感器值标识名:rainval读写类型:只读类型:数值
    数据范围:0 - 1023分辨率:1增量:0
    备注: 雨滴传感器数值



  • 名称:土壤湿度传感器值标识名:soilval读写类型:只读类型:数值
    数据范围:0 - 1023分辨率:1增量:0



  • 名称:光传感器值标识名:lightval读写类型:只读类型:数值
    数据范围:0 - 1023分辨率:1增量:0
    备注: 光传感器值



  • 名称:窗帘打开位置标识名:curtainpos读写类型:可写类型:数值
    数据范围:0 - 100分辨率:1增量:0



  • 名称:自动收衣位置标识名:dresspos读写类型:可写类型:数值
    数据范围:0 - 100分辨率:1增量:0



  • 名称:窗户是否被打开标识名:windowsopen读写类型:报警类型:布尔值




名称:电视遥控器1标识名:TVremote1读写类型:可写类型:枚举
枚举范围:0.无操作 1.开机/关机 2.频道+ 3.频道- 4.音量+ 5.音量- 6.静音 7.数字0 8.数字1 9.数字2 10.数字3 11.数字4 12.数字5 13.数字6 14.数字7 15.数字8 16.数字9 17.-/-- 18.返回 19.菜单 20.↑ 21.↓ 22.← 23.→ 24.确认 25.伴音 26.睡眠 27.制式 28.信号源 29.画中画

  • 名称:电视遥控2标识名:TVremote2读写类型:可写类型:枚举
    枚举范围:0.无操作 1.开机/关机 2.频道+ 3.频道- 4.音量+ 5.音量- 6.静音 7.数字0 8.数字1 9.数字2 10.数字3 11.数字4 12.数字5 13.数字6 14.数字7 15.数字8 16.数字9 17.-/-- 18.返回 19.菜单 20.↑ 21.↓ 22.← 23.→ 24.确认 25.伴音 26.睡眠 27.制式 28.信号源 29.画中画



  • 名称:自动亮度控制标识名:autolight1读写类型:可写类型:布尔值



  • 名称:音乐标识名:music读写类型:可写类型:枚举
    枚举范围:0.无操作 1.播放/暂停 2.上一曲 3.下一曲 4.音量加 5.音量减 6.停止 7.单曲循环 8.所有循环 9.停止循环 10.随机播放一首歌曲



  • 名称:是否监测窗户标识名:chuanghujiance读写类型:可写类型:布尔值



  • 名称:电视遥控器3标识名:TVremote3读写类型:可写类型:枚举
    枚举范围:0.无操作 1.开机/关机 2.频道+ 3.频道- 4.音量+ 5.音量- 6.静音 7.数字0 8.数字1 9.数字2 10.数字3 11.数字4 12.数字5 13.数字6 14.数字7 15.数字8 16.数字9 17.-/-- 18.返回 19.菜单 20.↑ 21.↓ 22.← 23.→ 24.确认 25.伴音 26.睡眠 27.制式 28.信号源 29.画中画



  • 名称:空调遥控器1标识名:KTremote1读写类型:可写类型:枚举
    枚举范围:0.无操作 1.开机/关机 2.模式 3.温度+ 4.温度- 5.健康模式 6.睡眠模式 7.保留1 8.保留2 9.保留3 10.保留4
    备注: 空调遥控



  • 名称:空调遥控器2标识名:KTremote2读写类型:可写类型:枚举
    枚举范围:



  • 名称:空调遥控器3标识名:KTremote3读写类型:可写类型:枚举
    枚举范围:



  • 名称:设置遥控器标识名:remotenum读写类型:可写类型:枚举
    枚举范围:0.无操作 1.退出遥控学习 2.电视遥控器1 3.电视遥控器2 4.电视遥控器3 5.空调遥控器1 6.空调遥控器2 7.空调遥控器3














智能家居-机智云接入串口通信协议文档.pdf

137.46 KB, 下载次数: 28, 下载积分: 威望 1

通信协议

7

主题

44

帖子

116

积分

注册会员

Rank: 2

积分
116
5#
 楼主| 发表于 2016-8-8 22:27:26 | 只看该作者
本次设计使用的单片机型号是MEGA64,首先来了解一下它的特性吧!(以下内容是copy于数据文档手册)
产品特性
• 高性能、低功耗的 8 位AVR® 微处理器
• 先进的RISC 结构
– 130 条指令 – 大多数指令执行时间为单个时钟周期
– 32个8 位通用工作寄存器
– 全静态工作
– 工作于16 MHz 时性能高达16 MIPS
– 只需两个时钟周期的硬件乘法器
• 非易失性程序和数据存储器
– 64K 字节的系统内可编程 Flash
擦写寿命: 10,000 次
– 具有独立锁定位的可选Boot 代码区
通过片上Boot 程序实现系统内编程
真正的同时读写操作
– 2K字节的EEPROM
擦写寿命: 100,000 次
– 4K字节片内SRAM
– 64K 字节可选外部存储空间
– 可以对锁定位进行编程以实现用户程序的加密
– 通过SPI 接口进行系统内编程
• JTAG 接口( 与IEEE 1149.1 标准兼容)
– 符合JTAG 标准的边界扫描功能
– 支持扩展的片内调试功能
– 通过JTAG 接口实现对Flash、EEPROM、熔丝位和锁定位的编程
• 外设特点
– 两个具有独立预分频器和比较器功能的8 位定时器/ 计数器
– 两个具有预分频器、比较功能和捕捉功能的扩展16 位定时器/ 计数器
– 具有独立振荡器的实时计数器RTC
– 两路8 位PWM 通道
– 6路编程分辨率从1 到 16 位可变的PWM 通道
– 8路10 位ADC
8 个单端通道
7 个差分通道
2 个具有可编程增益(1x, 10x, 或200x)的差分通道
– 面向字节的两线接口
– 可编程的串行USART
– 可工作于主机/ 从机模式的SPI 串行接口
– 具有独立片内振荡器的可编程看门狗定时器
– 片内模拟比较器
• 特殊的处理器特点
– 上电复位以及可编程的掉电检测
– 片内经过标定的RC 振荡器
– 片内/ 片外中断源
– 6种睡眠模式: 空闲模式、ADC 噪声抑制模式、省电模式、掉电模式、Standby 模式以及
扩展的Standby 模式
– 软件选择时钟频率
– 熔丝位选择的ATmega103 兼容模式
– 全局上拉禁止
• I/O 和封装
– 53个可编程的I/O 口
– 64引脚TQFP 封装, 与 64 引脚MLF 封装
• 工作电压
– ATmega64L:2.7 - 5.5V
– ATmega64:4.5 - 5.5V
• 速度等级
– ATmega64L:0 - 8 MHz

– ATmega64:0 - 16 MHz



本次设计整体IO引脚使用情况如下:


后面的发文,将会一个一个的进行阐述,并附上源代码。

7

主题

44

帖子

116

积分

注册会员

Rank: 2

积分
116
地板
 楼主| 发表于 2016-7-28 23:21:27 | 只看该作者
教您5分钟接入机智云,实现傻瓜式开发

    通过几天的考虑,为本次设计的智能家居系统做出如下的设计:
1、通过手机APP等移动设备,连接互联网机智云,通过ESP8266进行互联网通信,获取控制命令,并将命令通过RS232串口通信传给MCU:MEGA64,最终由MEGA64对具体的设备进行控制;
2、本次智能家居可进行操作或获取信息的内容主要为:
    a、智能开关:可以通过移动客户端远程对智能开关进行控制开关的通电与断电的操作。由此可衍伸出很多电器设备的控制,只要控制电源的开和关的,都可以通过智能开关进行控制。
    b、智能调光器:可以通过移动客户端,控制各电灯的亮暗,也可以通过环境亮度来进行自动控制。
    c、智能插座:和智能开关类似,只不过这个控制的是插座的通电和断电。
    d、智能窗帘:可以对窗帘的打开和关闭进行操作,也可以设定窗帘打开的多少,从而满足亮度的需要。
    e、智能自动收衣服:通过雨滴传感器传来的数据,判断现在是否下雨来对衣架的回收或伸展,保证衣服的干燥。
    f、智能风扇:可以控制风扇的转速。
    g、智能心情灯:可根据需要对RGB灯的三种颜色进行调节,从而控制灯的颜色,随心而变,增加氛围。
    h、智能音乐播放器:可以进行音乐的播放、暂停、上一曲、下一曲、随机播放、循环播放灯操作。
    i、智能安防窗户打开报警器:可进行安防监控,如果窗户被打开了,则会远程发送报警通知。
    j、智能红外解码转发器:可对各种电器的遥控器进行解码,并存储,然后通过远程控制发出相应的红外遥控信号进行控制电器,相当于遥控器。
    k、火焰防火灾报警器:监测家里的环境是否有着火现象,如有则进行消息通知。
    l、可燃气体报警器:监测环境中是否含有可燃气体,并达到一定的浓度后进行消息通知。
    m、自动浇花器:通过检测花盆中土壤的湿度进行控制是否对花浇水。
    n、温度、湿度表:通过检测环境的温度和湿度,并上报到移动客户端显示。


以上是对本次智能家居的任务设计方案,后面则对方案进行实际的选材设计与制作。
由于实际情况的限制,本次设计的一些内容,不是实际的220V交流电的操作,而是通过模拟的方式用5V直流电进行操作。其模拟的方法和220V交流电的实际操作方法是一致的,只是有些地方需要进行电路的设计,在后期的制作过程中也会给出这些设计。


智能家居.png (31.1 KB, 下载次数: 236)

【MEGA64+ESP8266】之智能家居系统结构图

【MEGA64+ESP8266】之智能家居系统结构图

7

主题

44

帖子

116

积分

注册会员

Rank: 2

积分
116
板凳
 楼主| 发表于 2016-7-25 10:11:55 | 只看该作者

好的,谢谢!

563

主题

1222

帖子

8097

积分

版主

Rank: 7Rank: 7Rank: 7

积分
8097
沙发
发表于 2016-7-25 01:07:36 来自手机 | 只看该作者
周一我在问问
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

加入Q群 返回顶部

版权与免责声明 © 2006-2024 Gizwits IoT Technology Co., Ltd. ( 粤ICP备11090211号 )

快速回复 返回顶部 返回列表