找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 21506|回复: 22
收起左侧

51单片机声控+语音播报的小风扇制作

  [复制链接]
ID:280994 发表于 2018-1-30 21:33 | 显示全部楼层 |阅读模式
这是一个能控制转速的风扇,我这个风扇特色功能(学校课程,为了加分)就是声音控制,语音提醒。机械结构是3D打印的。使用单片机芯片为STC12C5A60S2,音频DAC为TDA1543A(这个不太会用,这个项目中还有些问题,要仔细调调电位器才能发出正常声音),功放为LM386,咪头的放大器用的LM358。至于大家最关心的喇叭怎么说话的问题:声音数是通过电脑端用文本转语音软件生成的,是一个.wav文件,然后编个小程序把声音数据转换成数组,然后把这个数组掐头去尾只留中间(去除掉无用数据,51单片机储存实在小),再复制到单片机代码里的(由于弄个文件系统也很麻烦,而且速度很慢,所以就这样搞了)。具体原理(大神勿喷)是以一定的时间间隔(一般是8KHz)把数组中的数据通过DAC转换成电压信号输送给功放芯片,在经过功放芯片送给喇叭,这样由于变化的电压使喇叭震动,发出声音。
下面附上原理图,照片,代码和工程文件。请多多指教。

实物图

实物图

实物图

原理图

原理图

原理图

程序说明:
............................................................
版本号Beta0.0
本驱动工具包主要包含以下驱动(xxx.c文件和xxx.h文件共同使用,下面不再写后缀)
1“define.h”----包含了类型定义与开发板属性的设置(如晶振频率等)
2“delay”----定义了两个延时函数,支持STC大多数芯片(除15H系列..)
【提示】本函数库中驱动多数依赖于"delay.c""delay.h"和"define.h"文件
3“digital_display”----数码管显示驱动(硬件是基于两个373锁存器分别用作段数据和位数据)
4“digital_to_string”----包含了浮点数转换成字符串的函数
5“DS18B20”----温度传感器驱动
6“DS1302”----时钟芯片驱动
7“I2C”----软件模拟I2C总线驱动
8“Keyboard”----矩阵键盘驱动
9“LCD_1602_display”----1602液晶屏驱动(并口)
10“LCD_12864_display”----12864液晶屏驱动(并口带中文字库)(只是显示文字,不包含画图)
11“NEC_IR_coding”----用一个红外LED实现红外编码发射的驱动
12“NEC_IR_decoding”----红外解码驱动
13“NRF24L01”----2.4G无线通讯模块驱动
14“Uart”----串口驱动相关函数   
未完待续...
............................................................
............................................................
版本号Beta0.1
修复了数码管有关残影的bug
取消了矩阵键盘的松手检测,以检测不到键按下时返回0代替
未完待续...
............................................................
............................................................
版本号Beta0.2
加入了独立按键的检测,兼容矩阵按键,修复了矩阵键盘关于不同开发板兼容性的bug
增加了串口不同波特率的初始化程序
未完待续...
............................................................
............................................................
版本号Beta0.3
调整了数码管显示驱动的结构代码,方便不同开发板移植
未完待续...
............................................................

main.c
  1. #include "define.h"
  2. #include "delay.h"
  3. #include "mic.h"
  4. #include "play.h"
  5. #include "motor.h"
  6. #include "led.h"
  7. #include "sfkj.h"
  8. #include "zstz.h"
  9. u8 mode = 0; //速度级别
  10. void change_mode()
  11. {
  12.         static u8 i=0,j=0;     //计时变量约为8ms
  13.          if(mic_flag==2)
  14.                 {
  15.                          i++;
  16.                         if(i>10&&mic_flag==2)
  17.                         {
  18.                         //开机确认
  19.                                 if(mode==0)
  20.                                 {
  21.                                         Play_music(PCM8sfkj,sizeof(PCM8sfkj));
  22.                                         j=50;
  23.                                         mic_flag=0;
  24.                                         while(j--)
  25.                                         {
  26.                                                 delay_ms(100);
  27.                                                 if(mic_flag==2)
  28.                                                 {
  29.                                                         Play_music(PCM8zstz,sizeof(PCM8zstz));
  30.                                                         mode=1;
  31.                                                         mic_flag=0;
  32.                                                         break;
  33.                                                 }               
  34.                                         }
  35.                                 }
  36.                                 else if(mode==1)      
  37.                                 {      
  38.                                         mode=2;
  39.                                 }
  40.                                 else if(mode==2)      
  41.                                 {
  42.                                         Play_music(PCM8zstz,sizeof(PCM8zstz));                                       
  43.                                         mode=1;
  44.                                 }      
  45.                                 mic_flag=0;
  46.                                 i=0;
  47.                         }
  48.                 }
  49.                 else if(mic_flag==3)
  50.                 {
  51.                          i++;
  52.                         if(i>15&&mic_flag==3)
  53.                         {
  54.                           mode=0;
  55.                                 mic_flag=0;
  56.                                 i=0;
  57.                         }
  58.                 }
  59. }
  60. void change_PWM()
  61. {
  62.                 if(mode==0)
  63.                 {
  64.                         PCA_PWM0 = 0x03;
  65.                         CCAP0H = CCAP0L = 0xff;
  66.                 }
  67.                 else if(mode==1)
  68.                 {
  69.                         PCA_PWM0 = 0x00;
  70.                         CCAP0H = CCAP0L = CCAP0L-1;
  71.                 }
  72.                 else if(mode==2)
  73.                 {
  74.                         PCA_PWM0 = 0x00;
  75.                         CCAP0H = CCAP0L = CCAP0L;
  76.                 }
  77. }
  78. void main()
  79. {
  80.   Timer1Init();
  81.         IT0Init();
  82.         PWMInit();
  83.         Play_init();
  84.         delay_ms(1000);
  85.         while(1)
  86.         {
  87.                 change_mode();
  88.                     change_PWM();
  89.                 Digital_Display_One(CCAP0L/16);
  90.                 delay_ms(50);
  91.         }
  92.   
  93. }
  94. DELAY.c
  95. #include"DELAY.h"
  96. void delay_ms(uint ms)  
  97. {      
  98.          unsigned char i, j;
  99.         do
  100.         {                    
  101.                 i = TIME_I;
  102.                 j = TIME_J;
  103.                 do
  104.                 {
  105.                         while (--j);
  106.                 } while (--i);      
  107.         }while(--ms);
  108. }
  109. #if Machine_Cycle==12UL
  110. void delay5us()                //@12.000MHz
  111. {
  112.         _nop_();
  113. }
  114. #elif Machine_Cycle==2UL
  115. void delay5us()                //@12.000MHz
  116. {
  117.         unsigned char i;
  118.         i = 12;
  119.         while (--i);
  120. }
  121. #endif
  122. led.c
  123. #include "led.h"
  124. #define  Digital_Data P2
  125. code unsigned char leddata[]={
  126.                 0xB7,  //"0"
  127.                 0x06,  //"1"
  128.                 0x73,  //"2"
  129.                 0x57,  //"3"
  130.                 0xC6,  //"4"
  131.                 0xD5,  //"5"
  132.                 0xF5,  //"6"
  133.                 0x07,  //"7"
  134.                 0xF7,  //"8"
  135.                 0xD7,  //"9"
  136.                                                                 0xE7,  //"A"
  137.                 0xF4,  //"B"
  138.                 0xB1,  //"C"
  139.                 0x76,  //"D"
  140.                 0xF1,  //"E"
  141.                 0xE1,  //"F"
  142.                 0x00,  //熄灭
  143.                 0x00  //自定义
  144.                          };
  145. //函数名:Digital_Display_One
  146. //功能:                显示单个数码管
  147. //参数:                Digit:要显示的数字
  148. //                                pos:  要显示的位置
  149. //注意:                不同开发板只需要改写此函数,本文件其他数码管驱动即可使用
  150. void  Digital_Display_One(u8 Digit)
  151. {
  152.                 Digital_Data = leddata[Digit];
  153. }
  154. mic.c
  155. #include "mic.h"
  156. void IT0Init(void)                //100微秒@11.0592MHz
  157. {
  158.         IT0=1;
  159.         EX0=1;
  160.         EA=1;
  161. }
  162. void Timer1Init(void)                //50毫秒@11.0592MHz
  163. {
  164.         AUXR &= 0xBF;                //定时器时钟12T模式
  165.         TMOD &= 0x0F;                //设置定时器模式
  166.         TMOD |= 0x10;                //设置定时器模式
  167.         TL1 = 0x66;                //设置定时初值
  168.         TH1 = 0xFC;                //设置定时初值
  169.         TF1 = 0;                //清除TF1标志
  170.         TR1 = 1;                //定时器1开始计时
  171.         EA = 1;
  172.         ET1 = 1;
  173. }     
  174. u32 times=0;
  175. void T1INT() interrupt 3
  176. {
  177.         TL1 = 0x66;                //设置定时初值
  178.         TH1 = 0xFC;                //设置定时初值
  179.         times++;
  180. }
  181. u8 mic_flag=0;
  182. void EX0INT(void)  interrupt 0
  183. {  
  184.         static u32 last_time=0;
  185.         u32 differ;
  186.         differ=times-last_time;
  187.         last_time=times;
  188.         if(differ>1000)
  189.         {
  190.                 mic_flag=1;
  191.         }
  192.         else if(mic_flag>0&&differ>100&&differ<500)
  193.         {
  194.                  mic_flag++;
  195.         }
  196. }
  197. motor.c
  198. #include "motor.h"
  199. void PWMInit()
  200. {      
  201.         CCON = 0;                       //清除PCA控制寄存器
  202.                                  
  203.         CL = 0;                         //复位PCA定时器计数值
  204.         CH = 0;
  205.         CMOD=0x0a;                                                                                        //工作模式:频率=Sysclk/4/256=10800Hz 无中断
  206.       
  207.         CCAP0H = CCAP0L = 0xff;         //PWM0设置占空比50%
  208.         PCA_PWM0 = 0x03;
  209.         CCAPM0 = 0x42;                  //PCA模块0 工作在8比特方式 无中断
  210.         CR = 1;                         //PCA定时器运行
  211. }
  212. play.c
  213. #include "play.h"
  214. sbit I2SDATA=P1^4;
  215. sbit I2SWS = P1^5;
  216. sbit I2SBCK = P1^6;
  217. void I2S_Send(u8 dat)
  218. {
  219.         u8 i;
  220.         u8 t;               
  221.   I2SDATA=0;
  222.         for(i=0;i<8;i++)
  223.         {
  224.                 I2SBCK=1;
  225.                 I2SBCK=0;
  226.         }
  227.         t=dat;
  228.         for(i=0;i<8;i++)
  229.         {
  230.                 t=t<<1;
  231.                 I2SDATA=CY;
  232.                 I2SBCK=1;
  233.                 I2SBCK=0;
  234.         }
  235.         I2SWS=~I2SWS;
  236.         I2SBCK=1;
  237.         I2SBCK=0;
  238.       
  239. }
  240. void Play_init()
  241. {
  242.         I2S_Send(0x80);
  243.         I2S_Send(0x80);
  244.         I2S_Send(0x80);
  245.         I2S_Send(0x80);
  246. }
  247. void Play_music(u8 *Music,u16 sz)
  248. {
  249.         u16 i=0,j=0;
  250.         u8 flag=0;
  251.         for(i=0;i<sz;i++)
  252.         {
  253.                 I2S_Send(Music);      
  254.                 I2S_Send(0);
  255.         }                       
  256. }
  257. 音频数据
  258. code const u8 PCM8sfkj[]={
  259. 0x80,0x7e,0x80,0x86,0x7c,0x7a,0x81,0x7c,
  260. 0x80,0x87,0x7a,0x7c,0x87,0x7d,0x7a,0x86,
  261. 0x81,0x78,0x81,0x85,0x7c,0x7d,0x85,0x82,
  262. 0x7c,0x7c,0x82,0x81,0x7f,0x83,0x7e,0x7f,
  263. 0x80,0x7a,0x81,0x84,0x7f,0x7e,0x7e,0x80,
  264. };

  265. //只是一部分.........太长了...省略...可以去工程中看
复制代码
0.png

所有资料51hei提供下载:
我的风扇.rar (169.62 KB, 下载次数: 176)

评分

参与人数 4黑币 +115 收起 理由
jinmei1314 + 5 很给力!
凳子 + 5 绝世好帖!
qjzyx + 5 赞一个!
admin + 100 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:276118 发表于 2018-1-31 17:44 | 显示全部楼层
声音处理部分有学问
回复

使用道具 举报

ID:280994 发表于 2018-2-2 23:03 | 显示全部楼层
声音处理部分代码,纯C语言,在电脑上编译生成一个.exe可执行程序后,将音频文件复制到与.exe同级目录下,运行软件,输入音频文件名,回车
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <windows.h>
  4. #include "Music2.h"
  5. int main()
  6. {
  7.     FILE *fpwav,*fp;
  8.     int i=0,j=0,f;
  9.     int size=0;
  10.     short temp=0;
  11.     unsigned short u8data;
  12.     char s[30],cmd[30];
  13.     printf("Please input xx.wav\n");
  14.     scanf("%s",s);
  15.     if((fp=fopen("PCM8.h","w+"))==NULL)
  16.     {
  17.         printf("Can't Creat File\n");
  18.         system("pause");
  19.         exit(0);
  20.     }
  21.     if((fpwav=fopen(s,"rb"))==NULL)
  22.     {
  23.         printf("Can't Open %s\n",s);
  24.         system("pause");
  25.         exit(0);
  26.     }
  27.     fseek(fpwav,0x2a,0);
  28.     fread(&size,sizeof(int),1,fpwav);
  29.     printf("SIZE:%d\n",size);
  30.     printf("Wait process of %s......\n",s);
  31.     fseek(fpwav,0x2e,0);
  32.     rewind(fp);
  33.     fprintf(fp,"const u8 PCM8[]={\n");
  34.     for(i=1;i<=size/sizeof(short);i++)
  35.     {
  36.         for(j=0;j<8;j++)
  37.         {
  38.             f=fread(&temp,sizeof(short),1,fpwav);
  39.             u8data=temp*2+32768;
  40.             u8data=u8data/256;
  41.             fprintf(fp,"0x%x,",u8data);
  42.         }
  43.         fprintf(fp,"\n");
  44.     }
  45.     fprintf(fp,"\n};");
  46.     fclose(fp);
  47.     fclose(fpwav);
  48.     sprintf(cmd,"notepad.exe PCM8.h");
  49.     system(cmd);
  50.     system("pause");
  51.     return 0;
  52. }
复制代码
回复

使用道具 举报

ID:280568 发表于 2018-2-3 11:20 | 显示全部楼层
挺好的
回复

使用道具 举报

ID:266116 发表于 2018-2-3 13:23 | 显示全部楼层
很好的!谢谢分享
回复

使用道具 举报

ID:301192 发表于 2018-4-4 09:10 来自手机 | 显示全部楼层
楼主,下载了密码是多少呢
回复

使用道具 举报

ID:245836 发表于 2018-5-7 19:01 | 显示全部楼层
很好的!谢谢分享
回复

使用道具 举报

ID:324807 发表于 2018-5-8 10:05 | 显示全部楼层
不错哦,希望有用
回复

使用道具 举报

ID:48413 发表于 2018-5-15 08:37 | 显示全部楼层
很有创意啊
回复

使用道具 举报

ID:215044 发表于 2018-7-5 11:29 | 显示全部楼层
语音加播报功能很不错的创新
回复

使用道具 举报

ID:400844 发表于 2018-9-21 09:02 | 显示全部楼层
很给力
回复

使用道具 举报

ID:404066 发表于 2018-9-29 15:32 | 显示全部楼层
给力fight!
回复

使用道具 举报

ID:280994 发表于 2018-11-24 20:44 | 显示全部楼层
kkk123123123 发表于 2018-4-4 09:10
楼主,下载了密码是多少呢

没密码啊
回复

使用道具 举报

ID:474972 发表于 2019-2-26 16:59 来自手机 | 显示全部楼层
语音识别功能怎么实现的
回复

使用道具 举报

ID:489701 发表于 2019-3-20 09:20 | 显示全部楼层
不错哦,支持
回复

使用道具 举报

ID:63646 发表于 2019-4-28 18:54 | 显示全部楼层
声音处理部分代码,纯C语言,在电脑上编译生成一个.exe可执行程序后,将音频文件复制到与.exe同级目录下,运行软件,输入音频文件名,回车
vc6.0编译出现提示错误

21222.cpp(4) : fatal error C1083: Cannot open include file: 'Music2.h': No such file or directory
怎么处理
回复

使用道具 举报

ID:484435 发表于 2019-4-29 09:36 | 显示全部楼层
谢谢分享
回复

使用道具 举报

ID:468878 发表于 2019-4-29 12:07 | 显示全部楼层
还没有玩过音频啊!这个值得学习
回复

使用道具 举报

ID:280994 发表于 2019-5-1 12:08 | 显示全部楼层
longxiuchun 发表于 2019-4-28 18:54
声音处理部分代码,纯C语言,在电脑上编译生成一个.exe可执行程序后,将音频文件复制到与.exe同级目录下, ...

我是用的codeblocks,mingw编译器
回复

使用道具 举报

ID:280994 发表于 2019-5-1 12:10 | 显示全部楼层
XiNanShan 发表于 2019-2-26 16:59
语音识别功能怎么实现的

没有语音识别的功能,其实是拍手声音控制的
回复

使用道具 举报

ID:517235 发表于 2019-5-4 18:11 | 显示全部楼层
声音那里是用什么程序转换的呢
回复

使用道具 举报

ID:552708 发表于 2019-8-1 00:08 | 显示全部楼层
还没有玩过音频啊!这个值得学习
回复

使用道具 举报

ID:636039 发表于 2019-11-5 15:34 | 显示全部楼层
ws1336 发表于 2019-5-1 12:10
没有语音识别的功能,其实是拍手声音控制的

是不是 拍手频率越快  ,转速越快了 ??
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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