发 帖  
原厂入驻New
申请华秋企业认证 多层板首单免费打样!
30s提交资料,10分钟通过审核(免费赔付+顺丰包邮)>>立即报名
[创意DIY] stm32实现网络音频-原理图单片机程序C#上位机程序
2019-12-7 20:26:27  628 stm32 网络音频 上位机
分享
电子可以一边玩,一边研究,网络音频这个课题特别适合电子爱好者。几方面的挑战如下,单片机实现对接以太网、实时对音频流解码播放,上位机配合单片机做音频流传输控制,音频信号的对接放大处理。在这里分享下资料,自己把这些关键技术整理下。
原理图



PCB

上位机

实物

单片机关键程序
  1. #include "STM32f10x.h"
  2. #include "usart1.h"
  3. #include "Systick.h"
  4. #include "vs1053.h"
  5. #include "ch395.h"
  6. #include "sdio_sdcard.h"
  7. #include "ff.h"
  8. #include "diskio.h"
  9. #include <string.h>
  10. #include <stdio.h>
  11. #include "timer.h"

  12. u8  *ch395_T_Buffer="play over";
  13. u8  ch395_R_Buffer[2048];
  14. u8 play_count,Recv_count,Recv_H_flag,Recv_L_flag,play_H_flag,play_L_flag;
  15. u8 ch395_R_flag;
  16. u8  play_H_M,play_L_M;

  17. u8 Play_OK;
  18. ErrorStatus  HSEStartUpStatus;
  19. u16 count;

  20. void Play_1063_Duplex(void);

  21. const u8 CH395MACAddr[6] = {0x07,0x76,0x05,0x04,0x03,0x2};     // CH395MACµØÖ·         

  22. u8 CH395IPAddr[4] = {192,168,18,200};                       // CH395IPµØÖ·
  23. u8 CH395GWIPAddr[4] = {192,168,18,1};                      // CH395Íø¹Ø
  24. u8 CH395IPMask[4] = {255,255,255,0};                        // CH395×ÓÍøÑÚÂë


  25. u8  Socket0DesIP[4] = {192,168,18,10};                     /* Socket 0Ä¿µÄIPµØÖ· */
  26. u16 Socket0DesPort = 8888;                                  /* Socket 0Ä¿µÄ¶Ë¿Ú */
  27. u16 Socket0SourPort = 8888;                                 /* Socket 0Ô´¶Ë¿Ú */

  28. u8  Socket1DesIP[4] = {192,168,18,10};                     /* Socket 1Ä¿µÄIPµØÖ· */
  29. u16 Socket1DesPort = 34835;                                  /* Socket 1Ä¿µÄ¶Ë¿Ú */
  30. u16 Socket1SourPort = 34835;                                 /* Socket 1Ô´¶Ë¿Ú */

  31. u16 TIM3_count;
  32. u8 TIM3_flag;
  33.                         
  34. int main(void)
  35. {
  36.         SysTick_Init();                                                             /* ÅäÖÃSysTick Ϊ10usÖжÏÒ»´Î */      
  37.         USART1_Config();                                                      /* ÅäÖô®¿Ú1 115200 8-N-1 */
  38.         NVIC_Configuration();
  39.         vs1053_SPI_Init();        
  40.         CH395_SPI_Init();        
  41.         Delay_us(10000);
  42.         GPIO_SetBits(GPIOB, GPIO_Pin_0);
  43.         Delay_us(10000);
  44.         InitCH395InfParam();                                          /* ³õʼ»¯CH395Ïà¹Ø±äÁ¿ */
  45.         CH395Init();                                                  /* ³õʼ»¯CH395оƬ */
  46.         IF(CH395CMDGetPHYStatus() == PHY_DISCONN)                     /* ²éѯCH395ÊÇ·ñÁ¬½Ó */
  47.         {
  48.            Delay_us(2000);                                            /* δÁ¬½ÓÔòµÈ´ý200MSºóÔٴβéѯ */
  49.         }
  50.         InitSocketParam();                                            /* ³õʼ»¯socketÏà¹Ø±äÁ¿ */
  51.         CH395SocketInitOpen();

  52.         Delay_us(60000);
  53.         
  54.         vs1053_SPI_SPEED_L();         //³õʼ»¯ ĬÈÏΪmp3 ÓÃÓÚ²âÊÔ10KHz ·ñÔò ¿ª»úºóLED³£ÁÁ
  55.         MP3_Start();
  56.         vs1053_SPI_SPEED_H();

  57.         Timerx_Init(400,7199);
  58.         ch395_T_Buffer = "play";
  59.         CH395SendData(ch395_T_Buffer,sizeof(ch395_T_Buffer),Socket0DesIP,Socket0DesPort,0);
  60.         Delay_us(60000);
  61.         while (1)                        
  62.         {               
  63.                 GPIOB->BSRR = GPIO_Pin_2 ;
  64.                 CH395GlobalInterrupt();
  65.                 GPIOB->BRR = GPIO_Pin_2 ;
  66.                 Play_1063_Duplex();
  67.         }
  68. }

  69. void Play_1063_Duplex(void)
  70. {         
  71.         u16 i;
  72.         
  73.         GPIOB->BRR = GPIO_Pin_12 ;              // Ñ¡ÔñVS1053µÄÊý¾Ý½Ó¿Ú              
  74.         if(ch395_R_flag==1)
  75.         {
  76.                 ch395_R_flag=0;
  77.                
  78.                 while ( count < 1024)                           
  79.                 {        
  80.                         GPIOB->BSRR = GPIO_Pin_1 ;               
  81.                         if (GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10)!=0)               // µÈ´ýDREQΪ¸ß£¬ÇëÇóÊý¾ÝÊäÈë
  82.                         {                                                                                                                                
  83.                                 for (i=0; i<32; i++ ) // VS1053µÄFIFOÖ»ÓÐ32¸ö×ֽڵĻº³å
  84.                                 {                                                                                
  85.                                         vs1053_WriteByte(ch395_R_Buffer[count]);
  86.                                         count++;
  87.                                 }         
  88.                         }        
  89.                         GPIOB->BRR = GPIO_Pin_1 ;
  90.                 }
  91.                 if(count>1023)
  92.                 {
  93.                         count=0;
  94.                         CH395SendData(ch395_T_Buffer,sizeof(ch395_T_Buffer),Socket0DesIP,Socket0DesPort,0);
  95.                         memset(ch395_R_Buffer, 0, 1024);
  96.                         TIM3_count=0;
  97.                 }        
  98.         }
  99.         else
  100.         {
  101.                 if(TIM3_flag==1)
  102.                 {
  103.                         TIM3_flag=0;
  104.                         CH395SendData(ch395_T_Buffer,sizeof(ch395_T_Buffer),Socket0DesIP,Socket0DesPort,0);
  105.                 }
  106.         }
  107. }
复制代码
  1. void MP3_Start(void)
  2. {
  3.         u16 i;
  4.         GPIOB->BRR = GPIO_Pin_11;                                                                                                   
  5.   for (i=0; i<60000; i++ );
  6.         for (i=0; i<60000; i++ );
  7.         vs1053_WriteByte(0xff);                   // ·¢ËÍÒ»¸ö×Ö½ÚµÄÎÞЧÊý¾Ý£¬Æô¶¯SPI´«Êä
  8.         GPIOB->BSRR = GPIO_Pin_12;                                                
  9.         GPIOD->BSRR = GPIO_Pin_8;                                         
  10.         GPIOB->BSRR = GPIO_Pin_11;                                                      
  11.          for (i=0; i<60000; i++ );
  12.         for (i=0; i<60000; i++ );
  13.         VS_WR_Cmd(SPI_MODE,0x0800);          // ½øÈëvs1053µÄ²¥·Åģʽ
  14.         //VS_WR_Cmd(SPI_clockF, 0xf800);                       // ÉèÖÃvs1053µÄʱÖÓ,3±¶Æµ
  15.         VS_WR_Cmd(SPI_CLOCKF, 0xf800);                       // ÉèÖÃvs1053µÄʱÖÓ,3±¶Æµ
  16.         VS_WR_Cmd(SPI_AUDATA, 0xbb81);                       // ²ÉÑùÂÊ48k£¬Á¢ÌåÉù
  17.         VS_WR_Cmd(SPI_BASS, 0x0000);// ÉèÖÃÖصÍÒô
  18.         VS_WR_Cmd(SPI_VOL,0);                                        // vs1053 ÒôÁ¿
  19.         while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10)==0);//µÈ´ý¿ÕÏР                                                                  // µÈ´ýDREQΪ¸ß  ±íʾÄܹ»½ÓÊÜÒôÀÖÊý¾ÝÊäÈë

  20. }
复制代码
C#上位机程序
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using System.Windows.Forms;
  10. using System.Net.Sockets;
  11. using System.IO;
  12. using System.Net;
  13. using System.Threading;

  14. namespace WindowsFormsApplication12
  15. {
  16.     public partial class Form1 : Form
  17.     {
  18.         IPEndPoint udpPoint; //本机IP地址,端口号
  19.         IPEndPoint targetPoint; //服务器的IP地址,端口号
  20.         IPEndPoint Remote;
  21.         UdpClient udpClient;
  22.         UdpClient udpRecvClient;
  23.         int num = 0, readoffset = 0;
  24.         byte[] byData = new byte[1024];

  25.         private long Send_count;
  26.         private long Recv_count;
  27.         private long file_len;
  28.         private long file_close = 0;
  29.         private string file_nem;
  30.         int Recv_flag;

  31.         int Button_flag=0;

  32.         Thread Sendthread;
  33.         Thread Rcvethread;
  34.         Thread Showthread;

  35.         public Form1()
  36.         {
  37.             InitializeComponent();
  38.             udpPoint = new IPEndPoint(IPAddress.Parse("192.168.18.10"), 8888);
  39.             targetPoint = new IPEndPoint(IPAddress.Parse("192.168.18.200"), 8888);
  40.             Remote = new IPEndPoint(IPAddress.Any, 0);
  41.             Showthread = new Thread(Showstate);
  42.             Showthread.IsBackground = true;
  43.             Showthread.Start();
  44.         }
  45.         public delegate void CallSetTextbox();
  46.         private void SetTextbox()
  47.         {
  48.             try
  49.             {
  50.                 if (this.InvokeRequired)
  51.                 {
  52.                     CallSetTextbox myCallSetTextbox = new CallSetTextbox(SetTextbox);
  53.                     this.Invoke(myCallSetTextbox);
  54.                 }
  55.                 else
  56.                 {
  57.                     textBox1.Text = file_len.ToString();
  58.                 }
  59.             }
  60.             catch { }
  61.         }
  62.         private void SetSendTextbox()
  63.         {
  64.             try
  65.             {
  66.                 if (this.InvokeRequired)
  67.                 {
  68.                     CallSetTextbox myCallSetTextbox = new CallSetTextbox(SetSendTextbox);
  69.                     this.Invoke(myCallSetTextbox);
  70.                 }
  71.                 else
  72.                 {
  73.                     textBox2.Text = Send_count.ToString();
  74.                 }
  75.             }
  76.             catch { }
  77.         }
  78.         private void SetRecvTextbox()
  79.         {
  80.             try
  81.             {
  82.                 if (this.InvokeRequired)
  83.                 {
  84.                     CallSetTextbox myCallSetTextbox = new CallSetTextbox(SetRecvTextbox);
  85.                     this.Invoke(myCallSetTextbox);
  86.                 }
  87.                 else
  88.                 {
  89.                     textBox3.Text = Recv_count.ToString();
  90.                 }
  91.             }
  92.             catch { }
  93.         }
  94.         private void Showstate()
  95.         {
  96.             while (true)
  97.             {
  98.                 SetTextbox();
  99.                 SetSendTextbox();
  100.                 SetRecvTextbox();
  101.             }         
  102.         }
  103.         private void Udp_SendFunction()
  104.         {
  105.             try
  106.             {
  107.                 FileStream file = new FileStream(file_nem, FileMode.Open);//打开txt文件
  108.                 file_len=file.Length;
  109.                 file.Seek(0, SeekOrigin.Begin);
  110.                 while (true)
  111.                 {
  112.                     if (Recv_flag == 1)
  113.                     {
  114.                         Recv_flag = 0;
  115.                         num = file.Read(byData, readoffset, 1024);//读取txt文件内容
  116.                         udpClient.Send(byData, byData.Length, targetPoint);//发送数据

  117.                         Send_count = Send_count + 1024;

  118.                         if (num <= 0)
  119.                         {
  120.                             //MessageBox.Show("完成");
  121.                             break;
  122.                         }
  123.                         
  124.                     }
  125.                     if (file_close == 1)
  126.                     {
  127.                         file_close = 0;
  128.                         break;
  129.                     }
  130.                        
  131.                 }
  132.                 file.Close();//关闭txt文件
  133.             }
  134.             catch (IOException e)
  135.             {
  136.                 //MessageBox.Show("Send" + e.ToString());
  137.             }
  138.         }
  139.         private void Udp_RecvFunction()
  140.         {
  141.             //udpRecvClient = new UdpClient(udpPoint);//初始化udp
  142.             while (true)
  143.             {
  144.                 try
  145.                 {
  146.                     byte[] recBuffer = udpClient.Receive(ref Remote);
  147.                     if (recBuffer != null)
  148.                     {
  149.                         Recv_flag = 1;
  150.                         Recv_count = Recv_count + recBuffer.Length;
  151.                     }
  152.                 }
  153.                 catch (Exception ex)
  154.                 {
  155.                     //MessageBox.Show("Recv" + ex.ToString());
  156.                 }
  157.             }
  158.             
  159.         }
  160.         private void button1_Click(object sender, EventArgs e)
  161.         {
  162.             if (Button_flag == 0)
  163.             {
  164.                 file_close = 0;
  165.                 Send_count=0;
  166.                 Recv_count =0;
  167.                 file_len = 0;
  168.                 Button_flag = 1;
  169.                 udpClient = new UdpClient(udpPoint);//初始化udp
  170.                 using (OpenFiledialog ofd = new OpenFileDialog())
  171.                 {
  172.                     if (ofd.ShowDialog() == DialogResult.OK)  //如果点击的是打开文件
  173.                     {
  174.                         textBox4.Text = ofd.FileName;  //获取全路径文件名
  175.                         file_nem = ofd.FileName;               
  176.                         Sendthread = new Thread(Udp_SendFunction);
  177.                         Sendthread.IsBackground = true;
  178.                         Sendthread.Start();
  179.                         Rcvethread = new Thread(Udp_RecvFunction);
  180.                         Rcvethread.IsBackground = true;
  181.                         Rcvethread.Start();
  182.                         
  183.                     }
  184.                 }
  185.                 button1.ForeColor= Color.FromArgb(255, 155, 0, 0);
  186.                 button1.Text = "关闭文件";
  187.                 label5.Text = "播放中 ...";

  188.             }
  189.             else
  190.             {
  191.                 file_close = 1;
  192.                 Button_flag = 0;
  193.                 Send_count = 0;
  194.                 Recv_count = 0;
  195.                 file_len = 0;
  196.                 Sendthread.Abort();
  197.                 Rcvethread.Abort();                  
  198.                 button1.ForeColor = Color.FromArgb(255, 0, 155, 0);
  199.                 button1.Text = "打开文件";
  200.                 label5.Text = "已停止播放";
  201.                 udpClient.Close();
  202.             }
  203.             
  204.         }  
  205.     }
  206. }
复制代码


0
2019-12-7 20:26:27   评论 分享淘帖
高级模式
您需要登录后才可以回帖 登录 | 注册

发表新帖
关闭

站长推荐 上一条 /6 下一条

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