?? alarm.c
字號:
#include "COMM.H"
//鬧鐘部分代碼
//正點原子@SCUT
//全局變量區域
//鬧鐘結構體
typedef struct
{
u8 Status; //狀態寄存器 bit3,ON/OFF;bit2 RING/FM;bit 1,0 ONCE/EVERY DAY/SELF DEFINE
u8 WeekMark;//自定義標志
u8 Ring; //鬧鈴聲編號
u8 hour;
u8 min;
u8 Ring_Name[9];
u32 Ring_Addr;
}AlarmStruct;
AlarmStruct Alarm[8]; //鬧鐘暫存
AlarmStruct Alarm_Temp; //零時寄存區
u8 AlarmInLine=0;//在鬧鐘寄存器中的鬧鈴編號 0~7
u8 *Alarm_F1[8];//時間數據緩存區 XX:XX +'\0' 用于數據顯示
//存儲鈴聲
//存儲地址區間:300~411 總共112個字節
//type :鈴聲類型 0,MP3,1,FM
//Rnum :鈴聲編號 0~7
//RingN:鈴聲名字短文件名 對MP3
//RAddr:鈴聲地址/FM頻率
void Save_Ring(u8 type,u8 RNum,u8 *RingN,u32 RAddr)
{
u8 i;
if(type)//FM收音機 保存 103.6 (1036)之類的數據,占兩個字節
{
FM24C16_WriteOneByte(396+RNum*2+0,(RAddr>>8)&0xff);
FM24C16_WriteOneByte(396+RNum*2+1,RAddr&0xff);
}else
{
for(i=0;i<8;i++)FM24C16_WriteOneByte(300+RNum*12+i,RingN[i]);//把歌曲名字保存
FM24C16_WriteOneByte(300+RNum*12+8,(RAddr>>24)&0xff); //保存地址StartCluster
FM24C16_WriteOneByte(300+RNum*12+9,(RAddr>>16)&0xff);
FM24C16_WriteOneByte(300+RNum*12+10,(RAddr>>8)&0xff);
FM24C16_WriteOneByte(300+RNum*12+11,RAddr&0xff);
}
}
//讀取鈴聲
//地址區間:300~411 總共112個字節
//type :鈴聲類型
//Rnum :鈴聲編號
//RingN:鈴聲名字短文件名 對MP3
//RAddr:鈴聲地址/FM頻率
void Read_Ring(u8 type,u8 RNum,u8 *RingN,u32 *RAddr)
{
u8 i;
u8 temp[4];
if(type)//FM收音機 讀取 103.6 (1036)之類的數據,占兩個字節
{
temp[0]=FM24C16_ReadOneByte(396+RNum*2+0);
temp[1]=FM24C16_ReadOneByte(396+RNum*2+1);
*RAddr=(u32)temp[0]<<8;
*RAddr+=temp[1];
}else for(i=0;i<8;i++)
{
for(i=0;i<8;i++)*RingN++=FM24C16_ReadOneByte(300+RNum*12+i);
*RingN='\0';//添加結束符
temp[0]=FM24C16_ReadOneByte(300+RNum*12+8);
temp[1]=FM24C16_ReadOneByte(300+RNum*12+9);
temp[2]=FM24C16_ReadOneByte(300+RNum*12+10);
temp[3]=FM24C16_ReadOneByte(300+RNum*12+11);
*RAddr=(u32)temp[0]<<24;
*RAddr+=(u32)temp[1]<<16;
*RAddr+=(u32)temp[2]<<8;
*RAddr+=temp[3];
}
}
//存儲鬧鐘數據
//存儲地址區間:260~299 總共40個字節
//alx:要保存的編號 0~7,>=8,全部保存
void Save_Alarm(u8 alx)
{
u8 i;
if(alx<8)
{
FM24C16_WriteOneByte(260+alx*5,Alarm[alx].Status);
FM24C16_WriteOneByte(261+alx*5,Alarm[alx].WeekMark);
FM24C16_WriteOneByte(262+alx*5,Alarm[alx].Ring);
FM24C16_WriteOneByte(263+alx*5,Alarm[alx].hour);
FM24C16_WriteOneByte(264+alx*5,Alarm[alx].min);
Save_Ring(Alarm[alx].Status&0x04,Alarm[alx].Ring,Alarm[alx].Ring_Name,Alarm[alx].Ring_Addr); //保存MP3信息到相應的地址
}else for(i=0;i<8;i++)
{
FM24C16_WriteOneByte(260+i*5,Alarm[i].Status);
FM24C16_WriteOneByte(261+i*5,Alarm[i].WeekMark);
FM24C16_WriteOneByte(262+i*5,Alarm[i].Ring);
FM24C16_WriteOneByte(263+i*5,Alarm[i].hour);
FM24C16_WriteOneByte(264+i*5,Alarm[i].min);
Save_Ring(Alarm[alx].Status&0x04,Alarm[alx].Ring,Alarm[alx].Ring_Name,Alarm[alx].Ring_Addr); //保存MP3信息到相應的地址
}
}
//讀取鬧鐘數據
//存儲地址區間:260~299 總共40個字節
//alx:要讀取的編號 0~7,>=8,全部讀取
void Read_Alarm(u8 alx)
{
u8 i;
if(alx<8)
{
Alarm[alx].Status=FM24C16_ReadOneByte(260+alx*5);
Alarm[alx].WeekMark=FM24C16_ReadOneByte(261+alx*5);
Alarm[alx].Ring=FM24C16_ReadOneByte(262+alx*5);
Alarm[alx].hour=FM24C16_ReadOneByte(263+alx*5);
Alarm[alx].min=FM24C16_ReadOneByte(264+alx*5);
Read_Ring(Alarm[alx].Status&0x04,Alarm[alx].Ring,Alarm[alx].Ring_Name,&Alarm[alx].Ring_Addr);//讀取鬧鐘鈴聲信息
}else for(i=0;i<8;i++)
{
Alarm[i].Status=FM24C16_ReadOneByte(260+i*5);
Alarm[i].WeekMark=FM24C16_ReadOneByte(261+i*5);
Alarm[i].Ring=FM24C16_ReadOneByte(262+i*5);
Alarm[i].hour=FM24C16_ReadOneByte(263+i*5);
Alarm[i].min=FM24C16_ReadOneByte(264+i*5);
Read_Ring(Alarm[i].Status&0x04,Alarm[i].Ring,Alarm[i].Ring_Name,&Alarm[i].Ring_Addr);//讀取鬧鐘鈴聲信息
}
}
//初始化鬧鐘寄存器
//把鬧鐘0~7中的鬧鐘值取一個與當前時間最接近的放在鬧鐘寄存器里面
void Init_Alarm_Reg(void)
{
u8 i;
u8 temp;
u32 curtime=0;
u32 temptime=0;
u32 destime=0XFFFFFFFF;//設定到最大
u8 weekx;
u8 weektemp;
u8 t;
rtc_get();//得到時間
GetWeek(timer.w_year,timer.w_month,timer.w_date,&weekx);//得到星期 0~6 代表周末到周六
weekx=8-weekx;//與weekmark標志匹配
if(weekx==8)weekx=1;//周末處理
curtime=RTC->CNTH;//得到計數器中的值(秒鐘數)
curtime<<=16;
curtime+=RTC->CNTL;
//取一個與當前時間最接近的值作為鬧鐘寄存器的內容
for(i=0;i<8;i++)
{
temptime=curtime/86400; //得到當前運行天數
temptime=temptime*86400;
temptime+=(u32)Alarm[i].hour*3600+(u32)Alarm[i].min*60;//得到秒鐘數
temp=Alarm[i].Status;
if(temp&0x08)//鬧鐘開啟了
{
temp&=0x03;
switch(temp)
{
case 0://鬧鈴一次
case 1:
if(temptime<=curtime)temptime+=86400;//執行時間已過,推遲到明天
if(temptime<destime)
{
destime=temptime;//更改鬧鐘寄存器
AlarmInLine=i;//記錄保存在鬧鐘寄存器中的鬧鐘編號
}
break;
case 2://自定義鬧鐘
temp=Alarm[i].WeekMark;//周標記
if((temp&(1<<weekx))&&(temptime>curtime))//有標記當前的星期,且時間沒有超過
{
if(temptime<destime)
{
destime=temptime;//更改鬧鐘寄存器
AlarmInLine=i;//記錄保存在鬧鐘寄存器中的鬧鐘編號
}
}else
{
weektemp=weekx;
t=0;
while(1)
{
weektemp--;
if(weektemp<1)weektemp=7;
t++;
if(temp&(1<<weektemp))//有標記了
{
temptime+=(u32)t*86400;//更改鬧鐘寄存器,推后了t天
if(temptime<destime)
{
destime=temptime;
AlarmInLine=i;//記錄保存在鬧鐘寄存器中的鬧鐘編號
}
break;
}
if(weektemp==weekx)break;//經過了一個循環
}
}
break;
}
}
}
//讀取鬧鐘鈴聲信息
Read_Ring(Alarm[AlarmInLine].Status&0x04,Alarm[AlarmInLine].Ring,Alarm[AlarmInLine].Ring_Name,&Alarm[AlarmInLine].Ring_Addr);
printf("Alarm Num:%d\n",Alarm[AlarmInLine].Ring);//下一個鬧鐘的編號
printf("Alarm Addr:%d\n",Alarm[AlarmInLine].Ring_Addr);//下一個鬧鐘的編號
printf("Alarm Name:%s\n",Alarm[AlarmInLine].Ring_Name);//下一個鬧鐘的編號
printf("AlarmInLine:%d\n",AlarmInLine);//下一個鬧鐘的編號
//設置鬧鐘寄存器
RCC->APB1ENR|=1<<28;//使能電源時鐘
RCC->APB1ENR|=1<<27;//使能備份時鐘
PWR->CR|=1<<8; //取消備份區寫保護
//上面三步是必須的!
RTC->CRL|=1<<4; //允許配置
RTC->ALRL=destime&0xffff;
RTC->ALRH=destime>>16;
RTC->CRL&=~(1<<4);//配置更新
while(!(RTC->CRL&(1<<5)));//等待RTC寄存器操作完成
}
//顯示FM頻道信息
u16 Ring_Fm_Show(u8 rch)
{
u16 freqdiv;
BACK_COLOR=WHITE;
POINT_COLOR=BLACK;
TFT_ShowNum(136,114,rch,16,0x00); //顯示頻道值
freqdiv=FM24C16_ReadOneByte(60+rch*2);//讀取高位
freqdiv<<=8;//得到高位數據
freqdiv+=FM24C16_ReadOneByte(60+(rch*2)+1);//讀取低位
if(freqdiv>=10000)TFT_ShowChar(104,146,freqdiv/10000+'0',16,0x00);//在指定位置顯示一個字符
else TFT_ShowChar(104,146,' ',16,0x00);//在指定位置顯示一個字符
TFT_ShowChar(104,146,(freqdiv/1000)%10+'0',16,0x00);//在指定位置顯示一個字符
TFT_ShowChar(112,146,(freqdiv/100)%10+'0',16,0x00);//在指定位置顯示一個字符
TFT_ShowChar(120,146,'.',16,0x00);//在指定位置顯示一個字符
TFT_ShowChar(128,146,(freqdiv/10)%10+'0',16,0x00);//在指定位置顯示一個字符
return freqdiv;//返回頻率值
}
//設置鬧鈴/FM頻率
void Set_Alarm_Ring(void)
{
FileInfoStruct RingInfo;
u16 index;
u32 curdir=0;
u8 key;
u8 Ch_Num;//頻道總數
u8 CH_Val=0;
Load_Gui_Bro("完成");//顯示GUI界面
if(Alarm_Temp.Status&0x04)//收音機作為鈴聲
{
Ch_Num=FM24C16_ReadOneByte(58);//保存USA頻段最大電臺數 sCh_Num
if(Ch_Num==0)//沒有頻率供選擇.直接退出
{
Show_Str_Mid(0,114,"無任何頻道供選擇!",0x01,240); //疊加模式,非自動換行
return;
}
//加載GUI
POINT_COLOR=RED;
Show_Str_Mid(0,2,"FM鈴聲選擇",0x01,240); //疊加模式,非自動換行
POINT_COLOR=BLUE;
Show_Str(56,114,"頻道:",0x01); //疊加模式,非自動換行
Show_Str(56,146,"頻率: MHz",0x01); //疊加模式,非自動換行
//加載操作按鈕
BACK_COLOR=WHITE;
POINT_COLOR=BROWN;
TFT_ShowButton(104,110,1);//<
TFT_ShowButton(160,110,0);//>
index=Ring_Fm_Show(CH_Val);//顯示頻率等值
Pen_Point.Key_Sta=Key_Up;//釋放顯示期間的觸發
key=0;
while(1)//等待按鍵
{
if((Pen_Point.Key_Sta==Key_Down||NPEN)&&Pen_Point.Key_LSta)key=Touch_To_Num(4);//得到按鍵值
if(PEN)//按鍵松開了,狀態改變(狀態機)
{
Pen_Point.Key_LSta=1;
Pen_Point.Key_Sta=Key_Up;
}
if(key)//有按鍵按下
{
Pen_Point.Key_LSta=0;
if(Is_In_Area(104,110,128,134))//減少鍵
{
if(CH_Val)CH_Val--;
else CH_Val=Ch_Num-1;
index=Ring_Fm_Show(CH_Val);
}else if(Is_In_Area(160,110,184,134))//增加鍵
{
CH_Val++;
if(CH_Val>=Ch_Num)CH_Val=0;
index=Ring_Fm_Show(CH_Val);
}
if(key==9)//確認了
{
Save_Ring(1,Alarm_Temp.Ring,&key,index);//保存FM,寫入FM頻率時擴大十倍
return;
}else if(key==10)return;//返回
key=0;//取消按鍵值
}
delay_ms(1);
}
}else //MP3作為鈴聲
{
POINT_COLOR=RED;
Show_Str_Mid(0,2,"MP3鈴聲選擇",0x01,240);//疊加模式,非自動換行
curdir=Cur_Dir_Cluster;//保存上次的目錄簇號
if(FAT32_Enable)Cur_Dir_Cluster=FirstDirClust;//根目錄簇號
else Cur_Dir_Cluster=0;
index=File_Browse(T_MP3|T_WMA|T_WAV|T_MID);//瀏覽文件夾
if(index==0)
{
Cur_Dir_Cluster=curdir;//恢復上次的目錄簇號
return;//按下返回按鈕了
}
Get_File_Info(Cur_Dir_Cluster,&RingInfo,T_MP3|T_WMA|T_WAV|T_MID,&index);//得到這首歌曲的信息
Save_Ring(0,Alarm_Temp.Ring,RingInfo.F_ShortName,RingInfo.F_StartCluster);//保存MP3信息到相應的地址
for(index=0;index<8;index++)Alarm_Temp.Ring_Name[index]=RingInfo.F_ShortName[index];//得到新鬧鈴的名字
Alarm[Alarm_Temp.Ring].Ring_Addr=RingInfo.F_StartCluster;//得到新鬧鈴的地址,必須分配給ALARM
Cur_Dir_Cluster=curdir;//恢復上次的目錄簇號
}
}
//在中斷里面執行
//必須要用到獨立的RAM,否則可能影響其他程序的運行
u8 ALARMPLAYBUFFER[512];
//播放鬧鐘
void Play_Alarm_Ring(void)
{
u32 bfactor;
u32 bcluster;
u16 count;
u8 key,n;
u16 i;
u8 audioch;//音頻音源暫存器
FileInfoStruct RingInfo;
audioch=Audio_Ch;//記錄鬧鐘時的音源
read_dsp();
if(Alarm[AlarmInLine].Status&0x04)//收音機作為鈴聲
{
if(Alarm[AlarmInLine].Ring_Addr>10800||Alarm[AlarmInLine].Ring_Addr<8750)return;
init_pt2314(FM_Audio);//設置聲音
bfactor=frequency_set; //保留先前的頻率
n=JPUS;//保存先前的頻段
JPUS=USA;//設置到USA頻段
set_frequency(Alarm[AlarmInLine].Ring_Addr*10);//開啟收音機,到指定頻率
key=0;
Pen_Point.Key_Sta=Key_Up;
while(1)
{
if((Pen_Point.Key_Sta==Key_Down||NPEN)&&Pen_Point.Key_LSta)key=Touch_To_Num(6);//不使用擴展按鈕;
if(PEN)//按鍵松開了,狀態改變(狀態機)
{
Pen_Point.Key_LSta=1;
Pen_Point.Key_Sta=Key_Up;
}
if(key)
{
Pen_Point.Key_LSta=0;
if(key==1)break;//按中有效區域,退出播放
key=0;
}
}
JPUS=n; //恢復到原先的頻段
set_frequency(bfactor);//把收音機恢復到先前的頻率
}else //MP3作為鈴聲,播放歌曲
{
RingInfo.F_StartCluster=Alarm[AlarmInLine].Ring_Addr;
if(RingInfo.F_StartCluster<2)return;//沒有鈴聲
init_pt2314(MP3_Audio);//設置聲音
delay_ms(20);
Vs1003SoftReset();//軟復位VS1003
bfactor=fatClustToSect(RingInfo.F_StartCluster);//得到開始簇對應的扇區
bcluster=RingInfo.F_StartCluster; //得到文件開始簇號
key=0;
count=0;
Pen_Point.Key_Sta=Key_Up;//釋放按鍵
while(1) //播放音樂的主循環
{
if(SD_ReadSingleBlock(bfactor,ALARMPLAYBUFFER))break;//讀取一個扇區的數據
count++;//扇區計數器
i=0;
do //主播放循環
{
if((GPIOC->IDR&MP3_DREQ)!=0) //非暫停,送數據給VS1003
{
for(n=0;n<32;n++)Vs1003_DATA_Write(ALARMPLAYBUFFER[i++]);//發送音樂數據
}
if((Pen_Point.Key_Sta==Key_Down||NPEN)&&Pen_Point.Key_LSta)key=Touch_To_Num(6);//不使用擴展按鈕;
if(PEN)//按鍵松開了,狀態改變(狀態機)
{
Pen_Point.Key_LSta=1;
Pen_Point.Key_Sta=Key_Up;
}
if(key)
{
Pen_Point.Key_LSta=0;
if(key==1)goto PLAYOVER;//按中有效區域,退出播放
key=0;
}
}while(i<511);//循環發送512個字節
bfactor++; //扇區加
if(count>=SectorsPerClust)//一個簇結束,換簇
{
count=0;
bcluster=FAT_NextCluster(bcluster);
//文件結束
if((FAT32_Enable==0&&bcluster==0xffff)||bcluster==0x0ffffff8||bcluster==0x0fffffff)break;//error
bfactor=fatClustToSect(bcluster);
}
}
PLAYOVER:
Vs1003SoftReset();//軟復位
LoadPatch(); //加載頻譜分析代碼
Pen_Point.Key_LSta=0;
Pen_Point.Key_Sta=Key_Up;
}
init_pt2314(audioch);//恢復音源
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -