|
在此之前已经实现通过wifi发送WAV格式数据到开发板进行播放,请看:blog.csdn.net/chengdong1314/article/details/54352014
但是存在着一个十分重大的缺陷:所占能存过大,造成当和原来的微信的代码结合的时候发现会存在socket的read函数读取错误的现象,如下:
这个问题的主要原因是我这里声明了两个4K的数组,直接造成系统内存空间缺陷,如下:
从这里看要解决上面的问题只能够减少这个数组了,这里想想唯一还能够减少的就是把buf_temp这个数组去掉,这样意味着要重新修改flash的流程了。
下面为了彻底解决这个问题,这里进行了下面的优化:
1.把原来建立的our_main任务去掉,其代码移到et_user_main函数里做一个while(1)循环来进行
2.把原来的user_key_poll_task任务去掉,其代码放到user_main.c文件中的airkiss_key_poll_task函数来运行
3.优化flash的写操作函数,减掉一个4K的数组
下面是具体的实现步骤,在创建airkiss_key_poll_task任务之前先初始化user_key,如下:
wifi_set_event_handler_cb(et_wifi_event_cb);
memset(&key, 0, sizeof(key_gpio_t));
key.key_gpio_pin = AIRKISS_KEY_IO_PIN;
key.key_num = AIRKISS_KEY_IO_NUM;
airkiss_key_init(&key);
wifi_set_opmode(STATION_MODE);
gpio16_input_conf();
wifi_reconnect_start_flag = 0;
xTaskCreate(airkiss_key_poll_task, "smartconfig_task", 256, NULL, 2, NULL);
接下来在airkiss_key_poll_task的任务中同时也进行user_key按键的轮询判断,该任务修改后的整体代码如下:
airkiss_key_poll_task(void *pvParameters)
{
et_uint32 value, i;
while(1)
{
。。。。。。。。。
if(file_total_size100_save>0){
value = gpio16_input_get();
if(!value)
{
delay_ms(20);
value = gpio16_input_get();
if(!value)
{
audio_voice_data100 = 1;
file_total_size100=file_total_size100_save;
os_printf("play music again file_total_size:&x\n",file_total_size100);
delay_ms(5000);
}
}
}
delay_ms(500);
}
。。。。。。。。。。
}
该按键的主要工作是当如果已经存在接收完的音乐的时候这里将重播该音乐。
接下来就要去优化接收wav数据的过程和写flash的程序了,这里et_user_main函数的主要代码如下:
void et_user_main(void *pvParameters)
{
。。。。。。。。。
struct sockaddr_in remote_ip;
int recbytes=0,recbytes_temp=0;
char *recv_buf_temp=recv_buf;
et_uint32 download_file_size=0;
。。。。。。。。。。。
while(1){
while ((recbytes = read(sta_socket , (char *)(recv_buf+recbytes_temp), SPI_FLASH_SEC_SIZE-recbytes_temp)) > 0) {
recv_buf[recbytes] = 0;
recv_buf_temp=recv_buf;
os_printf("ESP8266 TCP client task > recv data %d bytes!\n", recbytes);
if(download_file_size==0){
if((strstr(recv_buf,"RIFF")==recv_buf) && (strstr((recv_buf+8),"WAV")==(recv_buf+8))){ //
download_file_size=(et_uint32)(((*(recv_buf+0x28)) | (*(recv_buf+0x29)<<8) | (*(recv_buf+0x2a)<<16) | (*(recv_buf+0x2b)<<24))-8);
recv_buf_temp =(char *)(recv_buf+0x2c); //从0x2b开始
recbytes -=0x2c;
file_total_size100=0;
sector100 = AUDIO_FLASH_START_SECTOR;
os_printf("WAV file not fatm 8K samply\n");
}
}
if(download_file_size){
os_printf("download_file_size:%X recv_buf:%x recbytes:%X\n",download_file_size,recv_buf_temp,recbytes);
recbytes_temp +=recbytes;
if((recbytes_temp>=SPI_FLASH_SEC_SIZE) || ((file_total_size100+recbytes_temp) >= download_file_size)){
write_flash_music(download_file_size,recv_buf_temp,recbytes_temp);
recbytes_temp=0;
}
if(audio_voice_data100){
download_file_size =0;
}
}else{
recbytes_temp=0;
}
}
if (recbytes <= 0) {
close(sta_socket);
os_printf("ESP8266 TCP client task > read data fail!\n");
}
}
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
}
这里的作用是用read函数来读取wav数据保存在recv_buf数组中,当总共读取到的数据大小recbytes_temp小于一个扇区的大小的时候将再次调用read函数读取SPI_FLASH_SEC_SIZE-recbytes_temp个字节的数据,直到总共读到的数据等于一个扇区的大小或者已经读取完了所有的WAV的数据的时候将调用 write_flash_music函数进行写flash操作,然后再重新接受下一个扇区的数据,这样就保证调用write_flash_music函数只有两种情况,其一是传输的数据大小恰好等于一个扇区的大小,其二是已经读取完所有的wav数据了,这也就不用再理会接下来的数据了,从之前的代码我们可以知道实现了上面的功能我们就能够省掉buf_temp。buf_temp这个数组主要是为了write_flash_music函数服务的,这个数组没了那么这个函数也要修改,其最终代码如下:
et_int32 write_flash_music (et_int32 file_size,et_char *data,et_int32 current_size)
{
et_int8 i=0;
et_int32 result=-1;
static et_int32 per_residue=0;
if(sector100 > AUDIO_FLASH_STOP_SECTOR) //超过flash,flash重新覆盖初始地址
{
file_total_size100 += current_size;
if(file_total_size100 >= file_size)
{
sector100 = AUDIO_FLASH_START_SECTOR;
file_total_size100 = AUDIO_FLASH_LEN - 1;
audio_voice_data100 = 1; //to inform interrupt of voice data coming //越界不播放,仍然下载完,只是覆盖
printf("file size > flash size.just play length of flash size(the former 45 seconds).\n");
file_total_size100_save=file_total_size100;
}
return 0;
}
result = spi_flash_erase_sector(sector100);
if(result != SPI_FLASH_RESULT_OK)
{
printf("spi_flash_erase_sector error\n");
return -1;
}
result = spi_flash_write(sector100 * SPI_FLASH_SEC_SIZE, (et_uint32 *)data, current_size); //write received voice data(4096 bytes) to flash
if(result != SPI_FLASH_RESULT_OK)
{
printf("spi_flash_write error\n");
return -1;
}
file_total_size100 += current_size;
sector100++;
os_printf("file_total_size:%x sector:%x per_residue:%x\n",file_total_size100,sector100,per_residue);
if(file_total_size100 >= file_size) //下载完成
{
if(file_size > AUDIO_FLASH_LEN) //文件总长度打印flash长度,只播放音频的flash长度
file_total_size100 = AUDIO_FLASH_LEN;
printf("down load file end.\n");
sector100 = AUDIO_FLASH_START_SECTOR;
audio_voice_data100 = 1; //to inform interrupt of being able to send voice data to i2s
file_total_size100_save=file_total_size100;
}
return 0;
}
从上面的代码可以看出,write_flash_music函数再也不会对传入的数据的大小做过多的处理,直接写入一个新的扇区,这是因为之前的代码已经保证了要么传入的数据是一个扇区,要么wav数据已经写完,对于上面的任何一种情况都不需要做过多的处理。
另外:对比我们现在的write_flash_music函数和开发快提供的write_flash_callback函数我们会惊人的发现,二者竟然何其的相似,简直一样,说明写开发板代码的思路和我的想法也是一样的,这也说明了我的水平是不低的,这还说明,如果开发快多开放一些资源,我就不用这样折腾了!哎!下面是write_flash_callback函数的代码:
et_int32 write_flash_callback (void *arg, const et_int64 file_size, const et_char *data, const et_int32 current_size)
{
et_int32 result=-1;
if (arg == NULL)
{
return EINVAL;
}
if(sector > AUDIO_FLASH_STOP_SECTOR) //超过flash,flash重新覆盖初始地址
{
file_total_size += current_size;
if(file_total_size >= file_size)
{
sector = AUDIO_FLASH_START_SECTOR;
file_total_size = AUDIO_FLASH_LEN - 1;
audio_voice_data = 1; //to inform interrupt of voice data coming //越界不播放,仍然下载完,只是覆盖
write_flash_end = 1; //to inform interrupt of being able to send voice data to i2s
printf("file size > flash size.just play length of flash size(the former 45 seconds).\n");
}
return 0;
}
result = spi_flash_erase_sector(sector);
if(result != SPI_FLASH_RESULT_OK)
{
printf("spi_flash_erase_sector error\n");
return -1;
}
result = spi_flash_write(sector * SPI_FLASH_SEC_SIZE, (et_uint32 *)data, current_size); //write received voice data(4096 bytes) to flash
if(result != SPI_FLASH_RESULT_OK)
{
printf("spi_flash_write error\n");
return -1;
}
file_total_size += current_size;
sector++;
if(file_total_size >= file_size) //下载完成
{
if(file_size > AUDIO_FLASH_LEN) //文件总长度打印flash长度,只播放音频的flash长度
file_total_size = AUDIO_FLASH_LEN;
printf("down load file end.\n");
sector = AUDIO_FLASH_START_SECTOR;
audio_voice_data = 1; //to inform interrupt of voice data coming
write_flash_end = 1; //to inform interrupt of being able to send voice data to i2s
}
return 0;
}
最后实验现象如下:
下面我将上传我的代码:download.csdn.net/detail/chengdong1314/9737621
下面是实验实验用到的音频以及录到的声音:download.csdn.net/detail/chengdong1314/9737623
|
阿莫论坛20周年了!感谢大家的支持与爱护!!
月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!
|