/* * 要想图片显示成功 * 需把字库拷贝到sd卡上,然后把sd卡插到开发板的卡槽上 */ int main(void) { LCD_Init(); LCD_Clear(0, 0, 240, 320, BACKGROUND); /* USART1 config */ //USART1_Config(); //printf("\r\n this is a fatfs test demo \r\n"); /* 初始化sd卡文件系统,因为汉字的字库放在了sd卡里面 */ Sd_fs_init(); /* 设置Lcd Gram 扫描方向为: 左上角 -> 右下角*/ //Lcd_GramScan( 1 ); LCD_DispStr(5, 5, (uint8_t *)"fatfs init success", RED); LCD_DispStr(5, 25, (uint8_t *)"insure the sdcard has insert......", RED); LCD_DispStrCH(50, 50, (uint8_t *)"野火开发板", RED); LCD_DispEnCh(5, 90, "Welcome to use 野火 ISO Stm32 开发板 bigo------", RED); /* 显示BMP图片 */ Lcd_show_bmp(0, 0,"/wildfire.bmp"); Lcd_show_bmp( 10,10,"/pic1.bmp"); Lcd_show_bmp( 170,0,"/pic2.bmp"); while(1); }
/*触摸时显示触摸效果*/ void Lcd_Touch(uint8_t test_num) { char i = ((test_num-1)%PER_PAGE); char pic_name[50]; sprintf(pic_name,"/boardtest/ISO_MINI/ui_tch_test%d.bmp",test_num); if(i<=((PER_PAGE/2)-1)) { Lcd_show_bmp(160, 166-(70*i),pic_name); } else { Lcd_show_bmp(91, 166-(70*(i-(PER_PAGE/2))),pic_name); } delay(0x2FFf); sprintf(pic_name,"/boardtest/ISO_MINI/ui_test%d.bmp",test_num); if(i<=((PER_PAGE/2)-1)) { Lcd_show_bmp(160, 166-(70*i),pic_name); } else { Lcd_show_bmp(91, 166-(70*(i-(PER_PAGE/2))),pic_name); } delay(0xFFF); }
/* * 初始化液晶,串口,触摸屏,flash及sd卡 * */ void ISO_Init(void) { uint8_t k; /* 液晶初始化先于串口,不然会有bug,至于是什么原因我也不知道:( */ LCD_Init(); LCD_Clear(0,0,240,320,WHITE); LCD_DispStr(20,150,"board init,please wait... ",RED); USART1_Config(); /* 初始化sd卡文件系统,因为汉字的字库放在了sd卡里面 */ Sd_fs_init(); #ifdef WORD_MODE /* 显示界面图片 */ Lcd_show_bmp(0, 0,"/boardtest/boardtest.bmp"); #else /* 显示界面图片 */ Lcd_show_bmp(0, 0,"/boardtest/ISO/ui_boardtest.bmp"); #endif Lcd_List(1); /* 初始化外部FLASH */ SPI_FLASH_Init(); //SPI_FLASH_SectorErase(0); /* 触摸屏IO和中断初始化 */ Touch_Init(); /*-------------------------------------------------------------------------------------------------------*/ #if 1 SPI_FLASH_BufferRead(&cal_flag, 0, 1); if( cal_flag == 0x55 ) { SPI_FLASH_BufferRead((void*)cal_p, 1, sizeof(cal_p)); SPI_FLASH_CS_HIGH(); for( k=0; k<6; k++ ) printf("\r\n rx = %LF \r\n",cal_p[k]); } else { /* 等待触摸屏校正完毕 */ while(Touch_Calibrate() !=0); } #elif 0 /* 等待触摸屏校正完毕 */ while(Touch_Calibrate() !=0); #endif }
void Lcd_List(char page) { #ifdef WORD_MODE //文字版 char i; char lcd_char[28]; //+4是为了预留空间的实验编号 select_index_boardtest=0; //重新显示新的一页时重置select_index Lcd_GramScan( 1 ); //设置扫描方向 LCD_Clear(12,86,206,145,BACKGROUND); sprintf(lcd_char,"第 %0d/%0d 页",current_page_boardtest,all_page_boardtest); //显示页码 LCD_DispEnCh(30,235,(const uint8_t *)lcd_char,BLUE); /* 打开playlist,读取音频文件名 */ for(i=0;(i+PER_PAGE*(page-1))<TEST_NUM && i< PER_PAGE;i++) //仅显示第一页 { sprintf(lcd_char,"%0d.%s",PER_PAGE*(page-1)+i+1,test_name[(PER_PAGE*(page-1) + i)]); //拼接出歌曲列表 LCD_DispEnCh(22,87+i*18,(const uint8_t *)lcd_char,BLACK); //显示 } #else //图标版 char i; char lcd_char[28]; //+4是为了预留空间的实验编号 char pic_name[50]; select_index_boardtest=0; //重新显示新的一页时重置select_index Lcd_GramScan( 1 ); //设置扫描方向 LCD_Clear(12,94,212,160,BACKGROUND);//BLUE BACKGROUND sprintf(lcd_char,"第 %0d/%0d 页",current_page_boardtest,all_page_boardtest); //显示页码 LCD_DispEnCh(30,235,(const uint8_t *)lcd_char,BLUE); /* 打开playlist,读取音频文件名 */ for(i=0;(i+PER_PAGE*(page-1))<TEST_NUM && i< PER_PAGE;i++) //仅显示第一页 { sprintf(pic_name,"/boardtest/ISO_MINI/ui_test%d.bmp",PER_PAGE*(page-1)+i+1); if(i<=((PER_PAGE/2)-1)) { Lcd_show_bmp(160, 166-(70*i),pic_name); } else { Lcd_show_bmp(91, 166-(70*(i-(PER_PAGE/2))),pic_name); } } #endif }
void MP3_test(void) { /* 初始化设置I2S */ I2S_Bus_Init(); /* 初始化PCM1770 */ PCM1770Init(); /* 显示MP3界面图片 */ Lcd_show_bmp(0, 0,"/mp3player/ui_window.bmp"); /* 运行MP3播放器 */ player_run(); }
void pic_display(void) { Lcd_show_bmp(0,0,"/pic3.bmp",1); // 显示MicroSD卡里面的MYPIC1.bmp文件,图片分辨率 Delay_us(300000); Lcd_show_bmp(0,0,"/1.bmp",1); // 显示MicroSD卡里面的MYPIC1.bmp文件,图片分辨率 Delay_us(300000); Lcd_show_bmp(0,0,"/2.bmp",1); // 显示MicroSD卡里面的MYPIC1.bmp文件,图片分辨 Delay_us(300000); Lcd_show_bmp(0,0,"/3.bmp",1); // 显示MicroSD卡里面的MYPIC1.bmp文件,图片分辨率 Delay_us(300000); Lcd_show_bmp(0,0,"/4.bmp",1); // 显示MicroSD卡里面的MYPIC1.bmp文件,图片分辨率 Delay_us(300000); Lcd_show_bmp(0,0,"/5.bmp",1); // 显示MicroSD卡里面的MYPIC1.bmp文件,图片分辨 Delay_us(300000); Lcd_show_bmp(0,0,"/6.bmp",1); // 显示MicroSD卡里面的MYPIC1.bmp文件,图片分辨率 Delay_us(300000); Lcd_show_bmp(0,0,"/myScreen.bmp",1); // 显示MicroSD卡里面的MYPIC1.bmp文件,图片分辨率 Delay_us(300000); }
int main(void) { /* USART1 config */ USART1_Config(); // Key3_GPIO_Config(); SysTick_Init(); key_led_init(); LCD_Init(); /* LCD 初始化*/ sd_fs_init(); Sd_fs_test(); // /*显示图像*/ // Lcd_show_bmp(0, 0,"/pic3.bmp"); // Lcd_show_bmp( 40,200,"/pic2.bmp"); // Lcd_show_bmp( 100,100,"/pic1.bmp"); // // /*横屏显示*/ // LCD_Str_O(20, 10, "lCD_DEMO",0); // LCD_Str_CH(20,30,"阿莫论坛野火专区",0,0xffff); // LCD_Str_CH_O(20,50,"阿莫论坛野火专区",0); // LCD_Num_6x12_O(20, 70, 65535, BLACK); // LCD_Str_6x12_O(20, 90,"LOVE STM32", BLACK); // /*竖屏显示*/ // LCD_Str_O_P(300, 10, "Runing", 0); // LCD_Str_CH_P(280,10,"阿莫论坛野火专区欢迎你",0xff,0xffff); // LCD_Str_CH_O_P(260,10,"阿莫论坛野火专区",0); // LCD_Str_6x12_O_P(240, 10,"LOVE STM32", 0); // LCD_Str_ENCH_O_P(220,10,"欢迎使用野火stm32开发板",0); // // /*截图*/ // LCD_Str_CH(20,150,"正在截图",0,0xffff); // Screen_shot(0, 0, 240,320 , "/myScreen"); // LCD_Str_CH(20,150,"截图完成",0,0xffff); // // // LCD_test(); // lcd_PutChar(50,30,'A',BLACK,WHITE); GUI_Text(20,30,"AAAAAAAAAAAAA ",sizeof("AAAAAAAAAAAAA "),0,0xffff); LCD_Char_CH(200,100,"好",0,0xffff); LCD_Str_CH(100,200,"呵呵,褚亭强你真牛逼",0,SILVER); Screen_shot(0, 0, 400,240 , "/myScreen"); LCD_Str_O(50,60,str2,BLACK,TEAL); Lcd_show_bmp(0,0,"/pic3.bmp",1); // 显示MicroSD卡里面的MYPIC1.bmp文件,图片分辨率1024*768 //LCD_WriteRAM_Prepare(); LCD_Str_O(50,80,str3,BLACK,SILVER); // ltk_list_file(); Lcd_show_bmp(0,0,"/1.bmp",1); // 显示MicroSD卡里面的MYPIC1.bmp文件,图片分辨率1024*768 Lcd_show_bmp(0,0,"/2.bmp",1); // 显示MicroSD卡里面的MYPIC1.bmp文件,图片分辨率1024*768 while (1) { pic_display(); } }
/** * @brief even_process 根据事件标志进行处理 * @param none * @retval none */ static void even_process(void) { switch(touch_even) { /* 音量加 */ case E_UP: Volume_Add(); touch_even = E_NULL; break; /* 音量减 */ case E_DOWN: Volume_Dec(); touch_even = E_NULL; break; /* 播放、暂停键 */ case E_PLAY_STOP: if(player_state == S_PLAY) //若当前状态为播放 { player_state = S_STOP; //切换为暂停状态 } else //若当前状态为暂停 player_state =S_PLAY; //切换为播放暂停 touch_even = E_NULL; break; /* 上一首 */ case E_PREV: if(play_index <= 0) { play_index = 0; } else { play_index--; #if 0 //放在player_run 函数里统一处理了 /* 检测要切换的歌曲是否在播放列表的上一页 */ if((play_index+8)/8 < current_page) //play_index从零开始计数所以+1,+7是使用进一法。 +1+7 =+8 { current_page--; //更新当前页码 lcd_list(current_page); //刷新LCD列表 } #endif } touch_even = E_NULL; player_state = S_SWITCH; //进入切歌状态 break; /* 下一首 */ case E_NEXT: if(play_index < file_num-1) { play_index++; #if 0 //放在player_run 函数里统一处理了 /* 检测要切换的歌曲是否在播放列表的下一页 */ if((play_index+8)/8 >current_page) //play_index从零开始计数所以+1,+7是使用进一法。 +1+7 =+8 { current_page++; //更新当前页码 lcd_list(current_page); //刷新LCD列表 } #endif } else { play_index = file_num-1; //play_index设置为最后一个歌曲文件 } touch_even = E_NULL; player_state = S_SWITCH; //进入切歌状态 break; /* 向上 */ case E_SELT_UP: if(select_index>0) select_index--; Lcd_GramScan(1); LCD_Clear(12,88,8,145,BACKGROUND); //清除状态栏 Lcd_show_bmp(320-(103+(select_index*18)),240-20,"/mp3player/ui_select.bmp"); //显示“打勾”标签 touch_even = E_NULL; break; /* 向下 */ case E_SELT_DOWN: if(select_index<8-1 && (select_index+8*(current_page-1))<file_num-1) //判断是否溢出,不大于8,不指向无文件名的位置 select_index++; Lcd_GramScan(1); LCD_Clear(12,88,8,145,BACKGROUND); //清除状态栏 Lcd_show_bmp(320-(103+(select_index*18)),240-20,"/mp3player/ui_select.bmp"); //显示“打勾”标签 touch_even = E_NULL; break; /* 直接点选歌曲 */ case E_SELECT: play_index = select_index + ((current_page-1)*8); //根据当前页和select_index确定play_index player_state = S_SWITCH; touch_even = E_NULL; break; /* 下一页 */ case E_SELT_NEXT: if(current_page<all_page) { current_page++; //更新当前页码 lcd_list(current_page); //刷新LCD列表 } else current_page =all_page; touch_even = E_NULL; break; /* 上一页 */ case E_SELT_PREV: if(current_page>1) { current_page--; //更新当前页码 lcd_list(current_page); //刷新LCD列表 } else current_page =1; touch_even = E_NULL; break; /* OK */ case E_SELT_OK: play_index = select_index+8*(current_page-1); //根据当前页和select_index确定play_index touch_even = E_NULL; player_state = S_SWITCH; break; /* 扬声器 */ case E_LOUD_SPEAK: if(speaker_flag == 0) //speaker关状态 { Loud_Speaker_ON(); //开启speaker speaker_flag =1; printf("\r\n loud on"); } else //speaker为开状态 { Loud_Speaker_OFF(); //关闭speaker speaker_flag=0; printf("\r\n loud off"); } touch_even = E_NULL; break; default: //touch_even = E_NULL; break; } }
/** * @brief wav_player 进行wav文件播放 * wav格式存储的就是PCM数据,不需要解码 * @param filename:要播放的文件路径 * @retval none */ static void wav_player(const char *filename) { short *p; WavHead *wav; //打开音频文件 fres = f_open (&file, filename, FA_READ ); //打开失败 if (fres!=FR_OK) { printf("read file %s error ! open another file\r\n",filename); fres = f_close (&file); if (++play_index>=file_num) //索引值加1 { play_index=0; //归0,所以如果所有文件都打开失败会一直循环 } return ; //文件无法打开,终止解码。进入下一次循环,读取下一个文件 } //显示播放图标 Lcd_GramScan(1); LCD_Clear(12,88,8,145,BACKGROUND); Lcd_show_bmp(320-(103+((play_index-((current_page-1)*8))*18)),240-20,"/mp3player/ui_playing.bmp"); fres = f_read(&file,buffer,512,&rw_num); //读取文件头 wav = (WavHead *)buffer; //整理格式 printf("\r\n samprate: %dHz", wav->dwSamplesPerSec); //采样率 if(wav->dwSamplesPerSec >= I2S_AudioFreq_Default) I2S_Freq_Config(wav->dwSamplesPerSec); //设置采样率 //播放循环 while(player_state != S_SWITCH) //循环本过程播放音频,直到切歌 { if (player_state == S_STOP) { even_process(); continue; //暂停的时候跳出本循环 } player_state = S_PLAY; //状态更新为正在播放 //读取wav文件 p = (short *)(buffer+sizeof(buffer)/2*bufflag); fres = f_read(&file, p, sizeof(buffer)/2, &rw_num); if(fres != FR_OK) { printf("读取%s失败! %d\r\n",filename,fres); break; } /* 等待DMA播放完,这段时间我们可以干其他的事,事件处理 */ while((DMA1_Channel5->CCR & DMA_CCR1_EN) && !(DMA1->ISR&DMA1_IT_TC5)) { even_process(); } DMA_ClearFlag(DMA1_FLAG_TC5 | DMA1_FLAG_TE5); DMA_I2S_Configuration((uint32_t)p, rw_num/2); bufflag = 1 -bufflag; //切换buffer if(file.fptr==file.fsize) //如果指针指向了文件尾,表示数据全部读完 { printf("END\r\n"); if(play_index<file_num-1) //自动开始下一首歌曲 { play_index++; player_state = S_SWITCH; } else { play_index = 0; player_state = S_SWITCH; } break; //跳出这首歌的播放状态 while break; } } f_close(&file); //结束播放本歌曲,关闭文件 I2S_Stop(); }
/** * @brief mp3_player 进行mp3文件解码、播放 * @param filename:要播放的文件路径 * @retval none */ static void mp3_player(const char *filename) { int err, i, outputSamps, current_sample_rate = 0; int read_offset = 0; /* 读偏移指针 */ int bytes_left = 0; /* 剩余字节数 */ unsigned long Frames = 0; /* mP3帧计数 */ unsigned char *read_ptr = buffer; /* 缓冲区指针 */ HMP3Decoder Mp3Decoder; /* mp3解码器指针 */ //打开音频文件 fres = f_open (&file, filename, FA_READ ); //打开失败 if (fres!=FR_OK) { printf("read file %s error ! open another file\r\n",filename); fres = f_close (&file); if (++play_index>=file_num) //索引值加1 { play_index=0; //归0,所以如果所有文件都打开失败会一直循环 } return ; //文件无法打开,终止解码。进入下一次循环,读取下一个文件 } //打开成功 //初始化MP3解码器 Mp3Decoder = MP3InitDecoder(); //获取输入数据流,调用helix库解码,输出PCM数据,约20ms完成一次循环 //开始进入播放状态,期间中断会修改touch_even状态 while(player_state != S_SWITCH) //循环1, 如果touch_even不是切歌状态则继续呆在循环体里 { //有时出现解码错误,错误后继续在本循环体内,继续播放 //显示播放图标 Lcd_GramScan(1); LCD_Clear(12,88,8,145,BACKGROUND); Lcd_show_bmp(320-(103+((play_index-((current_page-1)*8))*18)),240-20,"/mp3player/ui_playing.bmp"); //读取mp3文件 fres = f_read(&file, buffer, sizeof(buffer), &rw_num); if(fres != FR_OK) { printf("读取%s失败! %d\r\n",filename,fres); break; //return; } read_ptr = buffer; //指向mp3输入流 bytes_left = rw_num; //实际读到的输入流大小大小 //按帧处理 while(player_state != S_SWITCH) //循环2,循环本过程播放音频,直到按了下一首、上一首 { if (player_state == S_STOP) { even_process(); //检查是否有事件需要处理 continue; //暂停的时候结束本次循环 } player_state = S_PLAY; //状态更新为正在播放 read_offset = MP3FindSyncWord(read_ptr, bytes_left); //寻找帧同步,返回第一个同步字的位置 if(read_offset < 0) //没有找到同步字 { break; //跳出循环2,回到循环1 } read_ptr += read_offset; //偏移至同步字的位置 bytes_left -= read_offset; //同步字之后的数据大小 if(bytes_left < 1024) //补充数据 { /* 注意这个地方因为采用的是DMA读取,所以一定要4字节对齐 */ i=(uint32_t)(bytes_left)&3; //判断多余的字节 if(i) i=4-i; //需要补充的字节 memcpy(buffer+i, read_ptr, bytes_left); //从对齐位置开始复制 read_ptr = buffer+i; //指向数据对齐位置 fres = f_read(&file, buffer+bytes_left+i, sizeof(buffer)-bytes_left-i, &rw_num);//补充数据 bytes_left += rw_num; //有效数据流大小 } err = MP3Decode(Mp3Decoder, &read_ptr, &bytes_left, outBuf[bufflag], 0); //开始解码 参数:mp3解码结构体、输入流指针、输入流大小、输出流指针、数据格式 Frames++; if (err != ERR_MP3_NONE) //错误处理 { switch (err) { case ERR_MP3_INDATA_UNDERFLOW: printf("ERR_MP3_INDATA_UNDERFLOW\r\n"); read_ptr = buffer; fres = f_read(&file, read_ptr, sizeof(buffer), &rw_num); bytes_left = rw_num; break; case ERR_MP3_MAINDATA_UNDERFLOW: /* do nothing - next call to decode will provide more mainData */ printf("ERR_MP3_MAINDATA_UNDERFLOW\r\n"); break; default: printf("UNKNOWN ERROR:%d\r\n", err); // 跳过此帧 if (bytes_left > 0) { bytes_left --; read_ptr ++; } break; } } else //解码无错误,准备把数据输出到PCM { MP3GetLastFrameInfo(Mp3Decoder, &Mp3FrameInfo); //获取解码信息 /* 根据解码信息设置采样率 */ if (Mp3FrameInfo.samprate != current_sample_rate) //采样率 { current_sample_rate = Mp3FrameInfo.samprate; printf(" \r\n Bitrate %dKbps", Mp3FrameInfo.bitrate/1000); printf(" \r\n Samprate %dHz", current_sample_rate); printf(" \r\n BitsPerSample %db", Mp3FrameInfo.bitsPerSample); printf(" \r\n nChans %d", Mp3FrameInfo.nChans); printf(" \r\n Layer %d", Mp3FrameInfo.layer); printf(" \r\n Version %d", Mp3FrameInfo.version); printf(" \r\n OutputSamps %d", Mp3FrameInfo.outputSamps); if(current_sample_rate >= I2S_AudioFreq_Default) //I2S_AudioFreq_Default = 2,正常的帧,每次都要改速率 { I2S_Freq_Config(current_sample_rate); //根据采样率修改iis速率 } } /* 输出到DAC */ outputSamps = Mp3FrameInfo.outputSamps; //PCM数据个数 if (outputSamps > 0) { if (Mp3FrameInfo.nChans == 1) //单声道 { //单声道数据需要复制一份到另一个声道 for (i = outputSamps - 1; i >= 0; i--) { outBuf[bufflag][i * 2] = outBuf[bufflag][i]; outBuf[bufflag][i * 2 + 1] = outBuf[bufflag][i]; } outputSamps *= 2; } //非单声道数据可直接由DMA传输到IIS交给DAC /* 等待DMA播放完,这段时间我们可以干其他的事,扫描事件进行处理 */ while((DMA1_Channel5->CCR&DMA_CCR1_EN) && !(DMA1->ISR&DMA1_IT_TC5)) { even_process(); } /*DMA传输完毕*/ DMA_ClearFlag(DMA1_FLAG_TC5 | DMA1_FLAG_TE5); DMA_I2S_Configuration((uint32_t)outBuf[bufflag], outputSamps); bufflag = 1 -bufflag; //切换buffer }//if (outputSamps > 0) }//else 解码正常 if(file.fptr==file.fsize) //如果指针指向了文件尾,表示数据全部读完 { printf("END\r\n"); if(play_index<file_num-1) //自动开始下一首歌曲 { play_index++; player_state = S_SWITCH; //进入切歌状态,跳出 } else { play_index = 0; player_state = S_SWITCH; } break; //跳出这首歌的播放状态 while break; } }//循环2 内 while(player_state != S_SWITCH) }//循环1 外 while(player_state != S_SWITCH) f_close(&file); //结束播放本歌曲,关闭文件 MP3FreeDecoder(Mp3Decoder); I2S_Stop(); }