stm32实现网络音频-原理图单片机程序C#上位机程序

电子可以一边玩,一边研究,网络音频这个课题特别适合电子爱好者。几方面的挑战如下,单片机实现对接以太网、实时对音频流解码播放,上位机配合单片机做音频流传输控制,音频信号的对接放大处理。在这里分享下资料,自己把这些关键技术整理下。

原理图

PCB

上位机

实物

单片机关键程序

#include "stm32f10x.h"
#include "usart1.h"
#include "SysTick.h"
#include "vs1053.h"
#include "ch395.h"
#include "sdio_sdcard.h"
#include "ff.h"
#include "diskio.h"
#include <string.h>
#include <stdio.h>
#include "timer.h"

u8  *ch395_T_Buffer="play over";
u8  ch395_R_Buffer[2048]; 
u8 play_count,Recv_count,Recv_H_flag,Recv_L_flag,play_H_flag,play_L_flag;
u8 ch395_R_flag;
u8  play_H_M,play_L_M;

u8 Play_OK;
ErrorStatus  HSEStartUpStatus;
u16 count;

void Play_1063_Duplex(void);

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

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

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

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

u16 TIM3_count;
u8 TIM3_flag;
                        
int main(void)
{
	SysTick_Init();			                                     /* ÅäÖÃSysTick Ϊ10usÖжÏÒ»´Î */      
	USART1_Config(); 		                                     /* ÅäÖô®¿Ú1 115200 8-N-1 */
	NVIC_Configuration();
	vs1053_SPI_Init();	
	CH395_SPI_Init();	
	Delay_us(10000);
	GPIO_SetBits(GPIOB, GPIO_Pin_0);
	Delay_us(10000);
	InitCH395InfParam();                                          /* ³õʼ»¯CH395Ïà¹Ø±äÁ¿ */
	CH395Init();                                                  /* ³õʼ»¯CH395оƬ */
	if(CH395CMDGetPHYStatus() == PHY_DISCONN)                     /* ²éѯCH395ÊÇ·ñÁ¬½Ó */
	{
	   Delay_us(2000);                                            /* δÁ¬½ÓÔòµÈ´ý200MSºóÔٴβéѯ */
	}
	InitSocketParam();                                            /* ³õʼ»¯socketÏà¹Ø±äÁ¿ */
	CH395SocketInitOpen();

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

	Timerx_Init(400,7199);
	ch395_T_Buffer = "play";
	CH395SendData(ch395_T_Buffer,sizeof(ch395_T_Buffer),Socket0DesIP,Socket0DesPort,0);
	Delay_us(60000);
	while (1)			 
	{		
		GPIOB->BSRR = GPIO_Pin_2 ;
		CH395GlobalInterrupt();
		GPIOB->BRR = GPIO_Pin_2 ;
		Play_1063_Duplex();
	}
}

void Play_1063_Duplex(void)
{	 
	u16 i;
	
	GPIOB->BRR = GPIO_Pin_12 ;	      // Ñ¡ÔñVS1053µÄÊý¾Ý½Ó¿Ú 	     
	if(ch395_R_flag==1)
	{
		ch395_R_flag=0;
		
		while ( count < 1024)		   	
		{	
			GPIOB->BSRR = GPIO_Pin_1 ;		
			if (GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10)!=0) 	      // µÈ´ýDREQΪ¸ß£¬ÇëÇóÊý¾ÝÊäÈë 
			{																
				for (i=0; i<32; i++ ) // VS1053µÄFIFOÖ»ÓÐ32¸ö×ֽڵĻº³å 
				{										
					vs1053_WriteByte(ch395_R_Buffer[count]);
					count++;
				}	  
			}	
			GPIOB->BRR = GPIO_Pin_1 ;
		}
		if(count>1023)
		{
			count=0;
			CH395SendData(ch395_T_Buffer,sizeof(ch395_T_Buffer),Socket0DesIP,Socket0DesPort,0);
			memset(ch395_R_Buffer, 0, 1024); 
			TIM3_count=0;
		}	
	}
	else
	{
		if(TIM3_flag==1)
		{
			TIM3_flag=0;
			CH395SendData(ch395_T_Buffer,sizeof(ch395_T_Buffer),Socket0DesIP,Socket0DesPort,0);
		}
	}
}
void MP3_Start(void)
{
	u16 i;
	GPIOB->BRR = GPIO_Pin_11;          					 						
  for (i=0; i<60000; i++ );
	for (i=0; i<60000; i++ );
	vs1053_WriteByte(0xff);                   // ·¢ËÍÒ»¸ö×Ö½ÚµÄÎÞЧÊý¾Ý£¬Æô¶¯SPI´«Êä
	GPIOB->BSRR = GPIO_Pin_12;         					
	GPIOD->BSRR = GPIO_Pin_8;         				
	GPIOB->BSRR = GPIO_Pin_11;         			             	
 	for (i=0; i<60000; i++ );
	for (i=0; i<60000; i++ );
	VS_WR_Cmd(SPI_MODE,0x0800);  	// ½øÈëvs1053µÄ²¥·Åģʽ
	//VS_WR_Cmd(SPI_CLOCKF, 0xf800);   		    // ÉèÖÃvs1053µÄʱÖÓ,3±¶Æµ
	VS_WR_Cmd(SPI_CLOCKF, 0xf800);   		    // ÉèÖÃvs1053µÄʱÖÓ,3±¶Æµ
	VS_WR_Cmd(SPI_AUDATA, 0xbb81);   		    // ²ÉÑùÂÊ48k£¬Á¢ÌåÉù
	VS_WR_Cmd(SPI_BASS, 0x0000);// ÉèÖÃÖصÍÒô
	VS_WR_Cmd(SPI_VOL,0);       	                         // vs1053 ÒôÁ¿
	while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10)==0);//µÈ´ý¿ÕÏÐ						   	        // µÈ´ýDREQΪ¸ß  ±íʾÄܹ»½ÓÊÜÒôÀÖÊý¾ÝÊäÈë

}

C#上位机程序

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net.Sockets;
using System.IO;
using System.Net;
using System.Threading;

namespace WindowsFormsApplication12
{
    public partial class Form1 : Form
    {
        IPEndPoint udpPoint; //本机IP地址,端口号
        IPEndPoint targetPoint; //服务器的IP地址,端口号
        IPEndPoint Remote;
        UdpClient udpClient;
        UdpClient udpRecvClient;
        int num = 0, readoffset = 0;
        byte[] byData = new byte[1024];

        private long Send_count;
        private long Recv_count;
        private long file_len;
        private long file_close = 0;
        private string file_nem;
        int Recv_flag;

        int Button_flag=0;

        Thread Sendthread;
        Thread Rcvethread;
        Thread Showthread;

        public Form1()
        {
            InitializeComponent();
            udpPoint = new IPEndPoint(IPAddress.Parse("192.168.18.10"), 8888);
            targetPoint = new IPEndPoint(IPAddress.Parse("192.168.18.200"), 8888);
            Remote = new IPEndPoint(IPAddress.Any, 0);
            Showthread = new Thread(Showstate);
            Showthread.IsBackground = true;
            Showthread.Start();
        }
        public delegate void CallSetTextbox();
        private void SetTextbox()
        {
            try
            {
                if (this.InvokeRequired)
                {
                    CallSetTextbox myCallSetTextbox = new CallSetTextbox(SetTextbox);
                    this.Invoke(myCallSetTextbox);
                }
                else
                {
                    textBox1.Text = file_len.ToString();
                }
            }
            catch { }
        }
        private void SetSendTextbox()
        {
            try
            {
                if (this.InvokeRequired)
                {
                    CallSetTextbox myCallSetTextbox = new CallSetTextbox(SetSendTextbox);
                    this.Invoke(myCallSetTextbox);
                }
                else
                {
                    textBox2.Text = Send_count.ToString();
                }
            }
            catch { }
        }
        private void SetRecvTextbox()
        {
            try
            {
                if (this.InvokeRequired)
                {
                    CallSetTextbox myCallSetTextbox = new CallSetTextbox(SetRecvTextbox);
                    this.Invoke(myCallSetTextbox);
                }
                else
                {
                    textBox3.Text = Recv_count.ToString();
                }
            }
            catch { }
        }
        private void Showstate()
        {
            while (true)
            {
                SetTextbox();
                SetSendTextbox();
                SetRecvTextbox();
            }         
        }
        private void Udp_SendFunction()
        {
            try
            {
                FileStream file = new FileStream(file_nem, FileMode.Open);//打开txt文件
                file_len=file.Length;
                file.Seek(0, SeekOrigin.Begin);
                while (true)
                {
                    if (Recv_flag == 1)
                    {
                        Recv_flag = 0;
                        num = file.Read(byData, readoffset, 1024);//读取txt文件内容
                        udpClient.Send(byData, byData.Length, targetPoint);//发送数据

                        Send_count = Send_count + 1024;

                        if (num <= 0)
                        {
                            //MessageBox.Show("完成");
                            break;
                        }
                         
                    }
                    if (file_close == 1)
                    {
                        file_close = 0;
                        break;
                    }
                       
                }
                file.Close();//关闭txt文件
            }
            catch (IOException e)
            {
                //MessageBox.Show("Send" + e.ToString());
            }
        }
        private void Udp_RecvFunction()
        {
            //udpRecvClient = new UdpClient(udpPoint);//初始化udp
            while (true)
            {
                try
                {
                    byte[] recBuffer = udpClient.Receive(ref Remote);
                    if (recBuffer != null)
                    {
                        Recv_flag = 1;
                        Recv_count = Recv_count + recBuffer.Length;
                    }
                }
                catch (Exception ex)
                {
                    //MessageBox.Show("Recv" + ex.ToString());
                }
            }
            
        }
        private void button1_Click(object sender, EventArgs e)
        {
            if (Button_flag == 0)
            {
                file_close = 0;
                Send_count=0;
                Recv_count =0;
                file_len = 0;
                Button_flag = 1;
                udpClient = new UdpClient(udpPoint);//初始化udp
                using (OpenFileDialog ofd = new OpenFileDialog())
                {
                    if (ofd.ShowDialog() == DialogResult.OK)  //如果点击的是打开文件
                    {
                        textBox4.Text = ofd.FileName;  //获取全路径文件名
                        file_nem = ofd.FileName;               
                        Sendthread = new Thread(Udp_SendFunction);
                        Sendthread.IsBackground = true;
                        Sendthread.Start();
                        Rcvethread = new Thread(Udp_RecvFunction);
                        Rcvethread.IsBackground = true;
                        Rcvethread.Start();
                        
                    }
                }
                button1.ForeColor= Color.FromArgb(255, 155, 0, 0);
                button1.Text = "关闭文件";
                label5.Text = "播放中 ...";

            }
            else
            {
                file_close = 1;
                Button_flag = 0;
                Send_count = 0;
                Recv_count = 0;
                file_len = 0;
                Sendthread.Abort();
                Rcvethread.Abort();                   
                button1.ForeColor = Color.FromArgb(255, 0, 155, 0);
                button1.Text = "打开文件";
                label5.Text = "已停止播放";
                udpClient.Close();
            }
            
        }  
    }
}

猜你喜欢

转载自blog.csdn.net/gd1984812/article/details/103439088