|
这是一个能控制转速的风扇,我这个风扇特色功能(学校课程,为了加分)就是声音控制,语音提醒。机械结构是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 - #include "define.h"
- #include "delay.h"
- #include "mic.h"
- #include "play.h"
- #include "motor.h"
- #include "led.h"
- #include "sfkj.h"
- #include "zstz.h"
- u8 mode = 0; //速度级别
- void change_mode()
- {
- static u8 i=0,j=0; //计时变量约为8ms
- if(mic_flag==2)
- {
- i++;
- if(i>10&&mic_flag==2)
- {
- //开机确认
- if(mode==0)
- {
- Play_music(PCM8sfkj,sizeof(PCM8sfkj));
- j=50;
- mic_flag=0;
- while(j--)
- {
- delay_ms(100);
- if(mic_flag==2)
- {
- Play_music(PCM8zstz,sizeof(PCM8zstz));
- mode=1;
- mic_flag=0;
- break;
- }
- }
- }
- else if(mode==1)
- {
- mode=2;
- }
- else if(mode==2)
- {
- Play_music(PCM8zstz,sizeof(PCM8zstz));
- mode=1;
- }
- mic_flag=0;
- i=0;
- }
- }
- else if(mic_flag==3)
- {
- i++;
- if(i>15&&mic_flag==3)
- {
- mode=0;
- mic_flag=0;
- i=0;
- }
- }
- }
- void change_PWM()
- {
- if(mode==0)
- {
- PCA_PWM0 = 0x03;
- CCAP0H = CCAP0L = 0xff;
- }
- else if(mode==1)
- {
- PCA_PWM0 = 0x00;
- CCAP0H = CCAP0L = CCAP0L-1;
- }
- else if(mode==2)
- {
- PCA_PWM0 = 0x00;
- CCAP0H = CCAP0L = CCAP0L;
- }
- }
- void main()
- {
- Timer1Init();
- IT0Init();
- PWMInit();
- Play_init();
- delay_ms(1000);
- while(1)
- {
- change_mode();
- change_PWM();
- Digital_Display_One(CCAP0L/16);
- delay_ms(50);
- }
-
- }
- DELAY.c
- #include"DELAY.h"
- void delay_ms(uint ms)
- {
- unsigned char i, j;
- do
- {
- i = TIME_I;
- j = TIME_J;
- do
- {
- while (--j);
- } while (--i);
- }while(--ms);
- }
- #if Machine_Cycle==12UL
- void delay5us() //@12.000MHz
- {
- _nop_();
- }
- #elif Machine_Cycle==2UL
- void delay5us() //@12.000MHz
- {
- unsigned char i;
- i = 12;
- while (--i);
- }
- #endif
- led.c
- #include "led.h"
- #define Digital_Data P2
- code unsigned char leddata[]={
- 0xB7, //"0"
- 0x06, //"1"
- 0x73, //"2"
- 0x57, //"3"
- 0xC6, //"4"
- 0xD5, //"5"
- 0xF5, //"6"
- 0x07, //"7"
- 0xF7, //"8"
- 0xD7, //"9"
- 0xE7, //"A"
- 0xF4, //"B"
- 0xB1, //"C"
- 0x76, //"D"
- 0xF1, //"E"
- 0xE1, //"F"
- 0x00, //熄灭
- 0x00 //自定义
- };
- //函数名:Digital_Display_One
- //功能: 显示单个数码管
- //参数: Digit:要显示的数字
- // pos: 要显示的位置
- //注意: 不同开发板只需要改写此函数,本文件其他数码管驱动即可使用
- void Digital_Display_One(u8 Digit)
- {
- Digital_Data = leddata[Digit];
- }
- mic.c
- #include "mic.h"
- void IT0Init(void) //100微秒@11.0592MHz
- {
- IT0=1;
- EX0=1;
- EA=1;
- }
- void Timer1Init(void) //50毫秒@11.0592MHz
- {
- AUXR &= 0xBF; //定时器时钟12T模式
- TMOD &= 0x0F; //设置定时器模式
- TMOD |= 0x10; //设置定时器模式
- TL1 = 0x66; //设置定时初值
- TH1 = 0xFC; //设置定时初值
- TF1 = 0; //清除TF1标志
- TR1 = 1; //定时器1开始计时
- EA = 1;
- ET1 = 1;
- }
- u32 times=0;
- void T1INT() interrupt 3
- {
- TL1 = 0x66; //设置定时初值
- TH1 = 0xFC; //设置定时初值
- times++;
- }
- u8 mic_flag=0;
- void EX0INT(void) interrupt 0
- {
- static u32 last_time=0;
- u32 differ;
- differ=times-last_time;
- last_time=times;
- if(differ>1000)
- {
- mic_flag=1;
- }
- else if(mic_flag>0&&differ>100&&differ<500)
- {
- mic_flag++;
- }
- }
- motor.c
- #include "motor.h"
- void PWMInit()
- {
- CCON = 0; //清除PCA控制寄存器
-
- CL = 0; //复位PCA定时器计数值
- CH = 0;
- CMOD=0x0a; //工作模式:频率=Sysclk/4/256=10800Hz 无中断
-
- CCAP0H = CCAP0L = 0xff; //PWM0设置占空比50%
- PCA_PWM0 = 0x03;
- CCAPM0 = 0x42; //PCA模块0 工作在8比特方式 无中断
- CR = 1; //PCA定时器运行
- }
- play.c
- #include "play.h"
- sbit I2SDATA=P1^4;
- sbit I2SWS = P1^5;
- sbit I2SBCK = P1^6;
- void I2S_Send(u8 dat)
- {
- u8 i;
- u8 t;
- I2SDATA=0;
- for(i=0;i<8;i++)
- {
- I2SBCK=1;
- I2SBCK=0;
- }
- t=dat;
- for(i=0;i<8;i++)
- {
- t=t<<1;
- I2SDATA=CY;
- I2SBCK=1;
- I2SBCK=0;
- }
- I2SWS=~I2SWS;
- I2SBCK=1;
- I2SBCK=0;
-
- }
- void Play_init()
- {
- I2S_Send(0x80);
- I2S_Send(0x80);
- I2S_Send(0x80);
- I2S_Send(0x80);
- }
- void Play_music(u8 *Music,u16 sz)
- {
- u16 i=0,j=0;
- u8 flag=0;
- for(i=0;i<sz;i++)
- {
- I2S_Send(Music);
- I2S_Send(0);
- }
- }
- 音频数据
- code const u8 PCM8sfkj[]={
- 0x80,0x7e,0x80,0x86,0x7c,0x7a,0x81,0x7c,
- 0x80,0x87,0x7a,0x7c,0x87,0x7d,0x7a,0x86,
- 0x81,0x78,0x81,0x85,0x7c,0x7d,0x85,0x82,
- 0x7c,0x7c,0x82,0x81,0x7f,0x83,0x7e,0x7f,
- 0x80,0x7a,0x81,0x84,0x7f,0x7e,0x7e,0x80,
- };
- //只是一部分.........太长了...省略...可以去工程中看
复制代码
所有资料51hei提供下载:
我的风扇.rar
(169.62 KB, 下载次数: 177)
|
评分
-
查看全部评分
|