鳕鱼天空

This is Mr Wang's Tech Blog.

C++类中静态变量和静态方法使用介绍

静态成员的提出是为了解决数据共享的问题。实现共享有许多方法,如:设置全局性的变量或对象是一种方法。但是,全局变量或对象是有局限性的。这一章里,我们主要讲述类的静态成员来实现数据的共享。

  静态数据成员

  在类中,静态成员可以实现多个对象之间的数据共享,并且使用静态数据成员还不会破坏隐藏的原则,即保证了安全性。因此,静态成员是类的所有对象中共享的成员,而不是某个对象的成员。

  使用静态数据成员可以节省内存,因为它是所有对象所公有的,因此,对多个对象来说,静态数据成员只存储一处,供所有对象共用。静态数据成员的值对每个对象都是一样,但它的值是可以更新的。只要对静态数据成员的值更新一次,保证所有对象存取更新后的相同的值,这样可以提高时间效率。

  静态数据成员的使用方法和注意事项如下:

  1、静态数据成员在定义或说明时前面加关键字static。//静态变量的定义

  2、静态成员初始化与一般数据成员初始化不同。静态数据成员初始化的格式如下:

    <数据类型><类名>::<静态数据成员名>=<值>  //静态变量的初始化

  这表明:

         (1) 初始化在类体外进行,而前面不加static,(这点需要注意)以免与一般静态变量或对象相混淆。

  (2) 初始化时不加该成员的访问权限控制符private,public等。

  (3) 初始化时使用作用域运算符来标明它所属类,因此,静态数据成员是类的成员,而不是对象的成员。

  3、静态数据成员是静态存储的,它是静态生存期,必须对它进行初始化。

  4、引用静态数据成员时,采用如下格式:

   <类名>::<静态成员名>   //静态变量的使用方式

  如果静态数据成员的访问权限允许的话(即public的成员),可在程序中,按上述格式来引用静态数据成员。

  下面举一例子,说明静态数据成员的应用:

 
 1 class StaticTest
 2 {
 3 public:
 4     StaticTest(int a, int b, int c);
 5     void GetNumber();
 6     void GetSum();
 7     static void f1(StaticTest &s);
 8 private:
 9     int A, B, C;
10     static int Sum;
11 };
12 
13 
14 
15 #include "StaticTest.h"
16 #include <iostream>
17 using namespace std;
18 
19 int StaticTest::Sum = 0;//静态成员在此初始化
20 
21 StaticTest::StaticTest(int a, int b, int c)
22 {
23     A = a;
24     B = b;
25     C = c;
26     Sum += A + B + C;
27 }
28 
29 void StaticTest::GetNumber()
30 {
31     cout << "Number = " << endl;
32 }
33 
34 void StaticTest::GetSum()
35 {
36     cout << "Sum = " << Sum <<endl;
37 }
38 
39 void StaticTest::f1(StaticTest &s)
40 {
41     
42     cout << s.A << endl;//静态方法不能直接调用一般成员,可以通过对象引用实现调用
43     cout << Sum <<endl;
44 }
45 
46 #include "StaticTest.h"
47 #include <stdlib.h>
48 
49 
50 int main(void)
51 {
52     StaticTest M(3, 7, 10), N(14, 9, 11);
53     M.GetNumber();
54     N.GetSum();
55     M.GetNumber();
56     N.GetSum();
57     StaticTest::f1(M);
58     system("pause");
59     return 0;
60 }
 

 

注意,static成员的初始化要在实现中进行,不能在头文件进行。

从输出结果可以看到Sum的值对M对象和对N对象都是相等的。这是因为在初始化M对象时,将M对象的三个int型数据成员的值求和后赋给了Sum,于是Sum保存了该值。在初始化N对象时,对将N对象的三个int型数据成员的值求和后又加到Sum已有的值上,于是Sum将保存另后的值。所以,不论是通过对象M还是通过对象N来引用的值都是一样的,即为54,s.A=3。

静态成员函数

  静态成员函数和静态数据成员一样,它们都属于类的静态成员,它们都不是对象成员。因此,对静态成员的引用不需要用对象名。

  在静态成员函数的实现中不能直接引用类中说明的非静态成员,可以引用类中说明的静态成员(这点非常重要)。如果静态成员函数中要引用非静态成员时,可通过对象来引用。从中可看出,调用静态成员函数使用如下格式:<类名>::<静态成员函数名>(<参数表>);

 

转自: http://www.cnblogs.com/ppgeneve/p/5091794.html

C/C++中的实参和形参

最近迷上了arduino,打算用它写个传感小游戏,突然发现学的C++都还给老师了,还好有万能的度娘,特此留档。

1、值传递

    实参是变量,表达式等值。

    find(int x){}

    y= find(z);

   上面的例子中,z是实参,x是形参。x变z不变。

   在值传递过程中,实参和形参位于内存中两个不同地址中,实参先自己复制一次拷贝,再把拷贝复制给形参。所以,在值传递过程中,形参的变化不会对实参有任何的影响。

2、地址传递(也称引用传递)

   实参是指针。

   在函数调用的时候,实参传递给你的是指针地址,地址一样也就意味着实参和形参是一样的,当你的形参发生改变时,实参也会发生改变。

    find(int  &x){}

    y= find(z);

    上面的例子中,z是实参,x是形参。z随x而改变。

3、const引用传递

    find(const int  &x){}

    y= find(z);

    上面的例子中,z是实参,x是形参。z不随x而改变。

    有人就会问了,你这样做不是和值传递一样的么?NO!

    仔细观察就会发现,在值传递中要进行两次拷贝,浪费内存资源是相当可耻的,const的出现有效避免了这种情况的出现,只需拷贝一次就够了。

转自:http://www.cnblogs.com/kane0526/p/3913284.html

Arduino语音模块-DFPlayer Mini模块

Arduino语音模块-DFPlayer Mini模块

外观

外观

简介

  • DFPlayer Mini是一款小巧且价格低廉的MP3模块,可以直接接驳扬声器。
  • 模块配合供电电池、扬声器、按键可以单独使用,也可以通过串口控制,作为Arduino UNO或者是任何有串口的单片机的一个模块。
  • 模块本身完美的集成了MP3、WAV、WMA的硬解码。
  • 同时软件支持TF卡驱动,支持FAT16、FAT32文件系统。
  • 通过简单的串口指令即可完成播放指定的音乐,以及如何播放音乐等功能,无需繁琐的底层操作,使用方便,稳定可靠。

产品参数

  • 支持采样率(KHz):8/11.025/12/16/22.05/24/32/44.1/48
  • 24位DAC输出,动态范围支持:90dB,信噪比支持:85dB
  • 完全支持FAT16、FAT32文件系统,最大支持32G的TF卡,支持32G的U盘、64M字节的NORFLASH
  • 多种控制模式可选。IO控制模式、串口模式、AD按键控制模式
  • 广播语插播功能,可以暂停正在播放的背景音乐。广告播放完毕回到背景音继续播放
  • 音频数据按文件夹排序,最多支持100个文件夹,每隔文件夹可以分配255首曲目
  • 30级音量可调,6级EQ可调

引脚说明

DFPlayer_Mini_Pin

引脚号 引脚名称 功能描述 备注
1 VCC 模块电源输入 3.3V—5V,建议5V,不要超过5.2V
2 RX UART串行数据输入  
3 TX UART串行数据输出  
4 DAC_R 音频输出右声道 驱动耳机、功放
5 DAC_L 音频输出左声道 驱动耳机、功放
6 SPK2 接小喇叭 驱动小于3W喇叭
7 GND 电源地
8 SPK1 接小喇叭 驱动小于3W喇叭
9 IO1 触发口 默认上一曲(长按音量减)
10 GND 电源地
11 IO2 触发口 默认下一曲(长按音量加)
12 ADKEY1 AD口1 当触发时是第一首(长按循环第一首)
13 ADKEY2 AD口2 当触发时是第五首(长按循环第五首)
14 USB+ USB+ DP 接U盘或插电脑的USB口
15 USB- USB- DM 接U盘或插电脑的USB口
16 Busy 播放状态 有音频,输出低;无音频,输出高

资料说明
串口模式

模块支持异步串口通讯模式,通过串口接受控制命令

串口指令格式

指令名称 对应功能 功能描述
$S 起始位0x7E 每条命令反馈均以$开头,即0x7E
VER 版本 版本信息[目前默认为0xFF]
Len len后字节个数 校验和不计算在内
CMD 命令字 表示具体的操作,比如播放/暂停等等
Feedback 命令反馈 是否需要反馈信息,1反馈,0不反馈
para1 参数1 查询的数据高字节(比如歌曲序号)
para2 参数2 查询的数据低字节
checksum 校验和[占两个字节] 累加和校验[不计起始位$]
$0 结束位 结束位0xEF

举个例子,如果我们制定播放NOR FLASH,就需要发送:7E FF 06 09 00 00 04 FF DD EF,数据长度为6,这6个字节分别是[FF 06 09 00 00 04]。 不计算起始、结束、和校验。再然后对得到的结果进行取反。

串口控制指令

CMD命令(指令) 对应的功能 参数(16位)
0x01 下一曲  
0x02 上一曲  
0x03 指定曲目(NUM) 1-2999
0x04 音量+  
0x05 音量-  
0x06 指定音量 0-30
0x07 指定EQ 0/1/2/3/4/5 Normal/Pop/Rock/Jazz/Classic/Bass
0x08 单曲循环指定曲目播放 1-2999
0x09 指定播放设备 1/2/3/4/5 U盘/SD/AUX/SLEEP/FLASH
0x0A 进入休眠——低功耗  
0x0B 保留  
0x0C 模块复位  
0x0D 播放  
0x0E 暂停  
0x0F 指定文件夹播放 1-10(需要自己设定)
0x10 扩音设置(无) [DH=1:开扩音][DL:设置增益0-31]
0x11 全部循环播放 [1:循环播放][0:停止循环播放]
0x12 指定MP3文件夹曲目 1-9999
0x13 插播广告 1-9999
0x14 支持15个文件夹 见下面的详细说明
0x15 停止播放,播放背景  
0x16 停止播放  

串口查询指令

CMD命令详解(指令) 对应的功能 参数(16位)
0x3C STAY  
0x3D STAY  
0x3E STAY  
0x3F 发送初始化参数 0-0x0F(低四位每位代表一种设备)
0x40 返回错误,请求重发  
0x41 应答  
0x42 查询当前状态  
0x43 查询当前音量  
0x44 查询当前EQ  
0x45 查询当前播放模式 该版本保留此功能
0x46 查询当前软件版本 该版本保留此功能
0x47 查询UDISK的总文件数  
0x48 查询TF卡的总文件数  
0x49 查询FLASH卡的总文件数  
0x4A 保留  
0x4B 查询UDISK的当前曲目  
0x4C 查询TF的当前曲目  
0x4D 查询FLASH的当前曲目  

AD按键模式

模块还支持AD按键控制方式,取代了传统了矩阵键盘的接法,这样做的好处是充分利用了MCU越来越强大的AD功能。设计简约而不简单,我们模块默认配置2个AD口,20个按键的阻值分配。

  • 按键使用示意原理图

DFPlayer_Mini

IO模式

本模块也支持简单的IO模式

DFPlayer_Mini

使用教程
连线图
DFPlayer_Mini

样例代码
注意:文件夹命名需要是mp3,放置在SD卡根目录下,而mp3文件命名需要是4位数字,例如"0001.mp3",放置在mp3文件夹下。 如需中英文命名,可以添加在数字后,例如"0001hello.mp3"或者"0001后来.mp3"。

库文件下载链接:DFPlayer_Mini_mp3

/*
 *  Copyright:  DFRobot
 *  name:       DFPlayer_Mini_Mp3 sample code
 *  Author:     lisper <lisper.li@dfrobot.com>
 *  Date:       2014-05-30
 *  Description:    sample code for DFPlayer Mini, this code is test on Uno
 *          note: mp3 file must put into mp3 folder in your tf card
 */
#include <SoftwareSerial.h>
#include <DFPlayer_Mini_Mp3.h>

void setup () {
    Serial.begin (9600);
    mp3_set_serial (Serial);    //set Serial for DFPlayer-mini mp3 module 
    mp3_set_volume (15);
}

void loop () {        
    mp3_play (1);
    delay (6000);
    mp3_next ();
    delay (6000);
    mp3_prev ();
    delay (6000);
    mp3_play (4);
    delay (6000);
}

/*
   mp3_play ();     //start play
   mp3_play (5);    //play "mp3/0005.mp3"
   mp3_next ();     //play next 
   mp3_prev ();     //play previous
   mp3_set_volume (uint16_t volume);    //0~30
   mp3_set_EQ ();   //0~5
   mp3_pause ();
   mp3_stop ();
   void mp3_get_state ();   //send get state command
   void mp3_get_volume (); 
   void mp3_get_u_sum (); 
   void mp3_get_tf_sum (); 
   void mp3_get_flash_sum (); 
   void mp3_get_tf_current (); 
   void mp3_get_u_current (); 
   void mp3_get_flash_current (); 
   void mp3_single_loop (boolean state);    //set single loop 
   void mp3_DAC (boolean state); 
   void mp3_random_play (); 
 */

疑难解答

  • 问 :Arduino控制DFPlayer mini时,喇叭有杂音,如何处理?

    答:在TX,RX与MP3模块的RX,TX之间连一个1k电阻。因为DFPlayer Mini模块工作电压应该是3.3V,而主控板传入电压为5V,因此需要1K左右电阻分压。

  • 问 :SD卡中的文件和文件夹名字有什么格式要求吗?

    答:函数mp3_play (1); 播放文件的格式为"0001***.mp3(或支持其他格式)". 您可能需要注意这些:

(1). 该音频文件的名称应该命名一个四位数字开始,如:

0001.mp3
0002Chasing The Sun.mp3
0003.mp3
0004Try.mp3
0010FourFiveSeconds.mp3 

MP3-1.png

(2).该音频文件应该放在“MP3”'它坐落在TF卡的根目录'文件夹;
MP3-2.png

本文转自:http://www.ncnynl.com/archives/201606/190.html 创客制作 ,整理自 DFRobot wiki