基于stm32f107 stm32cube 和 LWIP 协议实现 udp 组播通信
生活随笔
收集整理的這篇文章主要介紹了
基于stm32f107 stm32cube 和 LWIP 协议实现 udp 组播通信
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
最近在做一個(gè)基于stm32f107 實(shí)現(xiàn) UDP 組播通信的項(xiàng)目,項(xiàng)目基于 stm32cube 配置生成,如下圖:
UDP組播頭文件:
#ifndef __MULTICAST_H__ #define __MULTICAST_H__#include "lwip/udp.h" #include "lwip/pbuf.h" #include "lwip/igmp.h" #include "User.h"/*port */ #define UDP_MULTICASE_RECV_PORT 8642 // multicast port for recive #define UDP_MULTICASE_SEND_PORT 8642 // multicast port for send #define MULTUDP_BUF_SIZE 2048extern struct udp_pcb* udp_server_multi_pcb; //組播PCB控制塊 extern ip4_addr_t ipgroup_rev,ipgroup_send;void multicast_send_data(unsigned char * data,unsigned short len); void udp_server_rev(void *arg, struct udp_pcb *pcb, struct pbuf *p,const ip_addr_t *addr, u16_t port); void Multicast_Config( void ); void MulticastUDP_SendTest(void);#endif /* __MULTICAST_H__ */UDP組播C文件:
/********************************************************************************* @file udp_echoserver.c* @author MCD Application Team* @version V1.1.0* @date 31-July-2013* @brief UDP echo server******************************************************************************* @attention** <h2><center>© COPYRIGHT 2013 STMicroelectronics</center></h2>** Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");* You may not use this file except in compliance with the License.* You may obtain a copy of the License at:** http://www.st.com/software_license_agreement_liberty_v2** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.********************************************************************************//* Includes ------------------------------------------------------------------*/ #include "main.h" #include "lwip/pbuf.h" #include "lwip/udp.h" #include "lwip/tcp.h" #include "lwip.h" #include <string.h> #include <stdio.h> #include "multicast.h" #include "User.h"#define PRINT(...)/* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ struct udp_pcb* udp_server_multi_pcb; // 組播PCB控制塊 ip4_addr_t ipgroup_rev,ipgroup_send;// UDP發(fā)送 void multicast_send_data(unsigned char * data,unsigned short len) {struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT,len, PBUF_RAM);memcpy(p->payload, data, len);udp_sendto(udp_server_multi_pcb, p,&ipgroup_send,UDP_MULTICASE_SEND_PORT);pbuf_free(p);}// 組播接收,回調(diào)函數(shù) void udp_server_rev(void *arg, struct udp_pcb *pcb, struct pbuf *p,const ip_addr_t *addr, u16_t port) { #if 1ProtoFrame_t UdpRxTemp;if( p != NULL ){if( p->tot_len >= sizeof(ProtoFrame_t) )memcpy( (void *)&UdpRxTemp, p->payload, sizeof(ProtoFrame_t) );else memcpy( (void *)&UdpRxTemp,p ->payload,p->tot_len );// 校驗(yàn)數(shù)據(jù)是否符合協(xié)議if( (FrameCheck(&UdpRxTemp) == 1) || (FrameCheck(&UdpRxTemp) == 2) ){UdpRxCmd[UdpRxCmdWrite] = UdpRxTemp;UdpRxCmdWrite = (UdpRxCmdWrite+1)%MAX_CMD_BUFF;}if( FrameCheck(&UdpRxTemp) > 1 ) // 轉(zhuǎn)發(fā)數(shù)據(jù)到 485{TxCmd[TxCmdWrite] = UdpRxTemp;TxCmdWrite = (TxCmdWrite+1)%MAX_CMD_BUFF;}/* Free the p buffer */pbuf_free(p);}#else// 回顯功能/* Connect to the remote client */udp_connect(pcb, addr, UDP_MULTICASE_SEND_PORT);/* Tell the client that we have accepted it *///udp_send(pcb, p);udp_sendto(pcb, p,&ipgroup_send,UDP_MULTICASE_SEND_PORT);/* free the UDP connection, so we can accept new clients */udp_disconnect(pcb);/* Free the p buffer */pbuf_free(p);#endif }void Multicast_Config( void ) {err_t err;IP4_ADDR(&ipgroup_rev, 224,0,0,100); // 用于接收組播的地址IP4_ADDR(&ipgroup_send, 224,0,0,100); // 用于發(fā)送組播的地址 #if LWIP_IGMPigmp_joingroup(IP_ADDR_ANY,&ipgroup_rev); // 只需要將接收地址放入igmp組,發(fā)送的不需要 #endifudp_server_multi_pcb = udp_new();if ( udp_server_multi_pcb ){/* Bind the upcb to the UDP_PORT port *//* Using IP_ADDR_ANY allow the upcb to be used by any local interface */err = udp_bind(udp_server_multi_pcb,IP_ADDR_ANY,UDP_MULTICASE_RECV_PORT);if(err == ERR_OK){/* Set a receive callback for the upcb */udp_recv(udp_server_multi_pcb,udp_server_rev,NULL);}else{udp_remove(udp_server_multi_pcb);PRINT("can not bind pcb");}}else{PRINT("can not create pcb");}}// 測(cè)試發(fā)送的方法 void MulticastUDP_SendTest(void) {multicast_send_data("igmp test\r\n",11 ); }/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/注意,我在做好上面的代碼后發(fā)現(xiàn),能實(shí)現(xiàn)UDP發(fā)送,但收到不信號(hào),經(jīng)過多方查找發(fā)現(xiàn)是因?yàn)榫W(wǎng)絡(luò)接口配置有些問題,
找到stm32f1xx_hal_eth.c文件中的 ETH_MACDMAConfig 函數(shù) ,如下圖,將代碼改成:
?
/*** @brief Configures Ethernet MAC and DMA with default parameters.* @param heth: pointer to a ETH_HandleTypeDef structure that contains* the configuration information for ETHERNET module* @param err: Ethernet Init error* @retval HAL status*/ static void ETH_MACDMAConfig(ETH_HandleTypeDef *heth, uint32_t err) {ETH_MACInitTypeDef macinit;ETH_DMAInitTypeDef dmainit;uint32_t tmpreg1 = 0U;if (err != ETH_SUCCESS) /* Auto-negotiation failed */{/* Set Ethernet duplex mode to Full-duplex */(heth->Init).DuplexMode = ETH_MODE_FULLDUPLEX;/* Set Ethernet speed to 100M */(heth->Init).Speed = ETH_SPEED_100M;}/* Ethernet MAC default initialization **************************************/macinit.Watchdog = ETH_WATCHDOG_ENABLE;macinit.Jabber = ETH_JABBER_ENABLE;macinit.InterFrameGap = ETH_INTERFRAMEGAP_96BIT;macinit.CarrierSense = ETH_CARRIERSENCE_ENABLE;macinit.ReceiveOwn = ETH_RECEIVEOWN_ENABLE;macinit.LoopbackMode = ETH_LOOPBACKMODE_DISABLE;if (heth->Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE){macinit.ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE;}else{macinit.ChecksumOffload = ETH_CHECKSUMOFFLAOD_DISABLE;}macinit.RetryTransmission = ETH_RETRYTRANSMISSION_DISABLE;macinit.AutomaticPadCRCStrip = ETH_AUTOMATICPADCRCSTRIP_DISABLE;macinit.BackOffLimit = ETH_BACKOFFLIMIT_10;macinit.DeferralCheck = ETH_DEFFERRALCHECK_DISABLE;macinit.ReceiveAll = ETH_RECEIVEAll_DISABLE; // ETH_RECEIVEALL_ENABLE; // macinit.SourceAddrFilter = ETH_SOURCEADDRFILTER_DISABLE;macinit.PassControlFrames = ETH_PASSCONTROLFRAMES_BLOCKALL;macinit.BroadcastFramesReception = ETH_BROADCASTFRAMESRECEPTION_ENABLE;macinit.DestinationAddrFilter = ETH_DESTINATIONADDRFILTER_NORMAL;macinit.PromiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE;macinit.MulticastFramesFilter = ETH_MULTICASTFRAMESFILTER_NONE; // ETH_MULTICASTFRAMESFILTER_PERFECT;macinit.UnicastFramesFilter = ETH_UNICASTFRAMESFILTER_PERFECT;macinit.HashTableHigh = 0x0U;macinit.HashTableLow = 0x0U;macinit.PauseTime = 0x0U;macinit.ZeroQuantaPause = ETH_ZEROQUANTAPAUSE_DISABLE;macinit.PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS4;macinit.UnicastPauseFrameDetect = ETH_UNICASTPAUSEFRAMEDETECT_DISABLE;macinit.ReceiveFlowControl = ETH_RECEIVEFLOWCONTROL_DISABLE;macinit.TransmitFlowControl = ETH_TRANSMITFLOWCONTROL_DISABLE;macinit.VLANTagComparison = ETH_VLANTAGCOMPARISON_16BIT;macinit.VLANTagIdentifier = 0x0U;/*------------------------ ETHERNET MACCR Configuration --------------------*//* Get the ETHERNET MACCR value */tmpreg1 = (heth->Instance)->MACCR;/* Clear WD, PCE, PS, TE and RE bits */tmpreg1 &= ETH_MACCR_CLEAR_MASK;/* Set the WD bit according to ETH Watchdog value *//* Set the JD: bit according to ETH Jabber value *//* Set the IFG bit according to ETH InterFrameGap value *//* Set the DCRS bit according to ETH CarrierSense value *//* Set the FES bit according to ETH Speed value *//* Set the DO bit according to ETH ReceiveOwn value *//* Set the LM bit according to ETH LoopbackMode value *//* Set the DM bit according to ETH Mode value *//* Set the IPCO bit according to ETH ChecksumOffload value *//* Set the DR bit according to ETH RetryTransmission value *//* Set the ACS bit according to ETH AutomaticPadCRCStrip value *//* Set the BL bit according to ETH BackOffLimit value *//* Set the DC bit according to ETH DeferralCheck value */tmpreg1 |= (uint32_t)(macinit.Watchdog |macinit.Jabber |macinit.InterFrameGap |macinit.CarrierSense |(heth->Init).Speed |macinit.ReceiveOwn |macinit.LoopbackMode |(heth->Init).DuplexMode |macinit.ChecksumOffload |macinit.RetryTransmission |macinit.AutomaticPadCRCStrip |macinit.BackOffLimit |macinit.DeferralCheck);/* Write to ETHERNET MACCR */(heth->Instance)->MACCR = (uint32_t)tmpreg1;/* Wait until the write operation will be taken into account:at least four TX_CLK/RX_CLK clock cycles */tmpreg1 = (heth->Instance)->MACCR;HAL_Delay(ETH_REG_WRITE_DELAY);(heth->Instance)->MACCR = tmpreg1;/*----------------------- ETHERNET MACFFR Configuration --------------------*//* Set the RA bit according to ETH ReceiveAll value *//* Set the SAF and SAIF bits according to ETH SourceAddrFilter value *//* Set the PCF bit according to ETH PassControlFrames value *//* Set the DBF bit according to ETH BroadcastFramesReception value *//* Set the DAIF bit according to ETH DestinationAddrFilter value *//* Set the PR bit according to ETH PromiscuousMode value *//* Set the PM, HMC and HPF bits according to ETH MulticastFramesFilter value *//* Set the HUC and HPF bits according to ETH UnicastFramesFilter value *//* Write to ETHERNET MACFFR */(heth->Instance)->MACFFR = (uint32_t)(macinit.ReceiveAll |macinit.SourceAddrFilter |macinit.PassControlFrames |macinit.BroadcastFramesReception |macinit.DestinationAddrFilter |macinit.PromiscuousMode |macinit.MulticastFramesFilter |macinit.UnicastFramesFilter);/* Wait until the write operation will be taken into account:at least four TX_CLK/RX_CLK clock cycles */tmpreg1 = (heth->Instance)->MACFFR;HAL_Delay(ETH_REG_WRITE_DELAY);(heth->Instance)->MACFFR = tmpreg1;/*--------------- ETHERNET MACHTHR and MACHTLR Configuration --------------*//* Write to ETHERNET MACHTHR */(heth->Instance)->MACHTHR = (uint32_t)macinit.HashTableHigh;/* Write to ETHERNET MACHTLR */(heth->Instance)->MACHTLR = (uint32_t)macinit.HashTableLow;/*----------------------- ETHERNET MACFCR Configuration -------------------*//* Get the ETHERNET MACFCR value */tmpreg1 = (heth->Instance)->MACFCR;/* Clear xx bits */tmpreg1 &= ETH_MACFCR_CLEAR_MASK;/* Set the PT bit according to ETH PauseTime value *//* Set the DZPQ bit according to ETH ZeroQuantaPause value *//* Set the PLT bit according to ETH PauseLowThreshold value *//* Set the UP bit according to ETH UnicastPauseFrameDetect value *//* Set the RFE bit according to ETH ReceiveFlowControl value *//* Set the TFE bit according to ETH TransmitFlowControl value */tmpreg1 |= (uint32_t)((macinit.PauseTime << 16U) |macinit.ZeroQuantaPause |macinit.PauseLowThreshold |macinit.UnicastPauseFrameDetect |macinit.ReceiveFlowControl |macinit.TransmitFlowControl);/* Write to ETHERNET MACFCR */(heth->Instance)->MACFCR = (uint32_t)tmpreg1;/* Wait until the write operation will be taken into account:at least four TX_CLK/RX_CLK clock cycles */tmpreg1 = (heth->Instance)->MACFCR;HAL_Delay(ETH_REG_WRITE_DELAY);(heth->Instance)->MACFCR = tmpreg1;/*----------------------- ETHERNET MACVLANTR Configuration ----------------*//* Set the ETV bit according to ETH VLANTagComparison value *//* Set the VL bit according to ETH VLANTagIdentifier value */(heth->Instance)->MACVLANTR = (uint32_t)(macinit.VLANTagComparison |macinit.VLANTagIdentifier);/* Wait until the write operation will be taken into account:at least four TX_CLK/RX_CLK clock cycles */tmpreg1 = (heth->Instance)->MACVLANTR;HAL_Delay(ETH_REG_WRITE_DELAY);(heth->Instance)->MACVLANTR = tmpreg1;/* Ethernet DMA default initialization ************************************/dmainit.DropTCPIPChecksumErrorFrame = ETH_DROPTCPIPCHECKSUMERRORFRAME_ENABLE;dmainit.ReceiveStoreForward = ETH_RECEIVESTOREFORWARD_ENABLE;dmainit.FlushReceivedFrame = ETH_FLUSHRECEIVEDFRAME_ENABLE;dmainit.TransmitStoreForward = ETH_TRANSMITSTOREFORWARD_ENABLE;dmainit.TransmitThresholdControl = ETH_TRANSMITTHRESHOLDCONTROL_64BYTES;dmainit.ForwardErrorFrames = ETH_FORWARDERRORFRAMES_DISABLE;dmainit.ForwardUndersizedGoodFrames = ETH_FORWARDUNDERSIZEDGOODFRAMES_DISABLE;dmainit.ReceiveThresholdControl = ETH_RECEIVEDTHRESHOLDCONTROL_64BYTES;dmainit.SecondFrameOperate = ETH_SECONDFRAMEOPERARTE_ENABLE;dmainit.AddressAlignedBeats = ETH_ADDRESSALIGNEDBEATS_ENABLE;dmainit.FixedBurst = ETH_FIXEDBURST_ENABLE;dmainit.RxDMABurstLength = ETH_RXDMABURSTLENGTH_32BEAT;dmainit.TxDMABurstLength = ETH_TXDMABURSTLENGTH_32BEAT;dmainit.DescriptorSkipLength = 0x0U;dmainit.DMAArbitration = ETH_DMAARBITRATION_ROUNDROBIN_RXTX_1_1;/* Get the ETHERNET DMAOMR value */tmpreg1 = (heth->Instance)->DMAOMR;/* Clear xx bits */tmpreg1 &= ETH_DMAOMR_CLEAR_MASK;/* Set the DT bit according to ETH DropTCPIPChecksumErrorFrame value *//* Set the RSF bit according to ETH ReceiveStoreForward value *//* Set the DFF bit according to ETH FlushReceivedFrame value *//* Set the TSF bit according to ETH TransmitStoreForward value *//* Set the TTC bit according to ETH TransmitThresholdControl value *//* Set the FEF bit according to ETH ForwardErrorFrames value *//* Set the FUF bit according to ETH ForwardUndersizedGoodFrames value *//* Set the RTC bit according to ETH ReceiveThresholdControl value *//* Set the OSF bit according to ETH SecondFrameOperate value */tmpreg1 |= (uint32_t)(dmainit.DropTCPIPChecksumErrorFrame |dmainit.ReceiveStoreForward |dmainit.FlushReceivedFrame |dmainit.TransmitStoreForward |dmainit.TransmitThresholdControl |dmainit.ForwardErrorFrames |dmainit.ForwardUndersizedGoodFrames |dmainit.ReceiveThresholdControl |dmainit.SecondFrameOperate);/* Write to ETHERNET DMAOMR */(heth->Instance)->DMAOMR = (uint32_t)tmpreg1;/* Wait until the write operation will be taken into account:at least four TX_CLK/RX_CLK clock cycles */tmpreg1 = (heth->Instance)->DMAOMR;HAL_Delay(ETH_REG_WRITE_DELAY);(heth->Instance)->DMAOMR = tmpreg1;/*----------------------- ETHERNET DMABMR Configuration ------------------*//* Set the AAL bit according to ETH AddressAlignedBeats value *//* Set the FB bit according to ETH FixedBurst value *//* Set the RPBL and 4*PBL bits according to ETH RxDMABurstLength value *//* Set the PBL and 4*PBL bits according to ETH TxDMABurstLength value *//* Set the DSL bit according to ETH DesciptorSkipLength value *//* Set the PR and DA bits according to ETH DMAArbitration value */(heth->Instance)->DMABMR = (uint32_t)(dmainit.AddressAlignedBeats |dmainit.FixedBurst |dmainit.RxDMABurstLength | /* !! if 4xPBL is selected for Tx or Rx it is applied for the other */dmainit.TxDMABurstLength |(dmainit.DescriptorSkipLength << 2U) |dmainit.DMAArbitration |ETH_DMABMR_USP); /* Enable use of separate PBL for Rx and Tx *//* Wait until the write operation will be taken into account:at least four TX_CLK/RX_CLK clock cycles */tmpreg1 = (heth->Instance)->DMABMR;HAL_Delay(ETH_REG_WRITE_DELAY);(heth->Instance)->DMABMR = tmpreg1;if ((heth->Init).RxMode == ETH_RXINTERRUPT_MODE){/* Enable the Ethernet Rx Interrupt */__HAL_ETH_DMA_ENABLE_IT((heth), ETH_DMA_IT_NIS | ETH_DMA_IT_R);}/* Initialize MAC address in ethernet MAC */ETH_MACAddressConfig(heth, ETH_MAC_ADDRESS0, heth->Init.MACAddr); }這樣就可以正常收到組播端口發(fā)來的數(shù)據(jù)了!!
而且實(shí)際發(fā)現(xiàn),在我改了st32f1xx_hal_eth.c 中函數(shù) 后, LWIP_IGMP 宏即使為 0 也可以實(shí)現(xiàn)組播通信!!
代碼量比開啟?LWIP_IGMP 宏少了 2K 左右。但是就是所有的組播地址中的數(shù)據(jù)都會(huì)被收到,如果要針對(duì)某一地址進(jìn)行組播通信, LWIP_IGMP 宏還是要設(shè)為1才行。
總結(jié)
以上是生活随笔為你收集整理的基于stm32f107 stm32cube 和 LWIP 协议实现 udp 组播通信的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: lwip 开发 sntp 与 tcp 不
- 下一篇: 查看DLL 及LIB 库导出函数方法