环境:
开发环境:MDK5.23
rt-thread版本:2.1.0
lwip版本:1.4.1
单片机型号:stm32f407
phy芯片型号:
说明:
本程序是udp客户端模块。绑定固定端口进行收发。udp接收是一个线程,接收到数据利用邮箱机制推送到其他处理模块。udp发送提供了多种发送接口。
源码:
udp_socket.h
/**
* Copyright (c), 2015-2025
* @file udp_socket.h
* @brief udp端口头文件
* @author jdh
* @verbatim
* Change Logs:
* Date Author Notes
* 2017-12-22 jdh 新建
* @endverbatim
*/
#ifndef _UDP_SOCKET_H_
#define _UDP_SOCKET_H_
#include "drivers.h"
/**
* @brief 最大注册邮箱数
*/
#define MAX_NUM_UDP_SOCKET_MAILBOX 10
/**
* @brief 接收数据结构.邮箱会推送此结构指针
*/
struct UdpSocketRx
{
T_Buffer_Large buffer;
struct sockaddr_in sockaddr;
};
/**
* @brief 模块载入
*/
void udp_socket_load(void);
/**
* @brief 更新服务器信息
*/
void udp_socket_update_server_info(void);
/**
* @brief socket是否工作
* @return true: 工作.false: 不工作
*/
bool udp_socket_is_work(void);
/**
* @brief 发送数据
* @param data:发送数据存放地址
* @param size:发送数据字节数
* @param dst_ip: 目的ip
* @param dst_port: 目的端口
*/
void udp_socket_tx(uint8_t *data, uint16_t size, char *dst_ip, uint16_t dst_port);
/**
* @brief 发送数据
* @param data:发送数据存放地址
* @param size:发送数据字节数
* @param sockaddr: 目的地址
*/
void udp_socket_tx_sockaddr(uint8_t *data, uint16_t size, struct sockaddr_in sockaddr);
/**
* @brief 发送数据给服务器
* @param data:发送数据存放地址
* @param size:发送数据字节数
*/
void udp_socket_tx_server(uint8_t *data, uint16_t size);
/**
* @brief 发送数据给配置服务器
* @note 配置服务器无效则发送给服务器
* @param data:发送数据存放地址
* @param size:发送数据字节数
*/
void udp_socket_tx_config_server(uint8_t *data, uint16_t size);
/**
* @brief 注册邮箱
* @note 接收数据后会推送到此邮箱
* @param mailbox: 邮箱地址
*/
void udp_socket_register_mailbox(rt_mailbox_t mailbox);
/**
* @brief 增加传输层头后发送数据
* @param dst_device: 目标设备类型
* @param data: 发送数据存放地址
* @param size: 发送数据字节数
* @param sockaddr: 目的地址
*/
void udp_socket_tx_sockaddr_add_trans_head(uint8_t dst_device, uint8_t *data, uint16_t size, struct sockaddr_in sockaddr);
/**
* @brief 发送确认帧
* @param dst_device: 目标设备类型
* @param cmd: 确认帧命令字
* @param ack_cmd: 需要确认的命令
* @param sockaddr: 目的地址
*/
void udp_socket_tx_sockaddr_ack_frame(uint8_t dst_device, uint8_t cmd, uint8_t ack_cmd, struct sockaddr_in sockaddr);
/**
* @brief 增加传输层头后发送数据
* @param dst_device: 目标设备类型
* @param data: 发送数据存放地址
* @param size: 发送数据字节数
* @param sockaddr: 目的地址
*/
void udp_socket_tx_server_add_trans_head(uint8_t dst_device, uint8_t *data, uint16_t size);
/**
* @brief 发送确认帧
* @param dst_device: 目标设备类型
* @param cmd: 确认帧命令字
* @param ack_cmd: 需要确认的命令
* @param sockaddr: 目的地址
*/
void udp_socket_tx_server_ack_frame(uint8_t dst_device, uint8_t cmd, uint8_t ack_cmd);
#endif
udp_socket.c
/**
* Copyright (c), 2015-2025
* @file udp_socket.c
* @brief udp端口主文件
* @author jdh
* @verbatim
* Change Logs:
* Date Author Notes
* 2017-12-22 jdh 新建
* 2017-12-26 jdh 增加网络和lwip功能
* @endverbatim
*/
#include "framework.h"
#include "stm32f4xx_eth.h"
#include #define TAG "LOG_UDP" /** * @brief 配置帧超时时间.单位:ms.超过这个时间,射频模块的回复就不会再发向配置服务器 */ #define CONFIG_TIMEOUT 500 /** * @brief 启动稳定期.单位:ms */ #define STARTUP_WAIT_TIME 1000 /** * @brief 日志项编号 */ static uint8_t _log_item = 0; static int _socket; static bool _is_net_work = false; static struct sockaddr_in _server_addr; static struct UdpSocketRx _udp_socket_rx; /** * @brief 配置服务器的地址 */ static struct sockaddr_in _config_server_addr; static T_Time _last_config_frame_time; /** * @brief 邮箱数组 */ static struct rt_mailbox *_mailbox_array[MAX_NUM_UDP_SOCKET_MAILBOX]; static uint8_t _len_mailbox_array = 0; /** * @brief 发送数据 */ static T_Buffer_Large Buffer_Tx; static void thread_init(void* parameter); static void init_lwip(void); static void set_ip(void); static void bind_socket(void); static void socket_rx(void); static bool is_frame_valid(void); static inline void send_mailbox(void); /** * @brief 模块载入 */ void udp_socket_load(void) { _log_item = log_register(TAG); #ifdef RT_USING_LWIP rt_thread_t tid_init = rt_thread_create("init_net", thread_init, (void*)0, THREAD_STACK_NORMAL, THREAD_PRIORITY_NORMAL, THREAD_SLICE_NORMAL); rt_thread_startup(tid_init); #endif } static void thread_init(void* parameter) { init_lwip(); udp_socket_update_server_info(); bind_socket(); socket_rx(); } static void init_lwip(void) { /* LwIP Initialization */ { extern void lwip_sys_init(void); /* register ethernetif device */ eth_system_device_init(); // rt_hw_stm32_eth_init(); rt_hw_stm32_eth_init_my(); /* init lwip system */ lwip_sys_init(); rt_kprintf("TCP/IP initialized!n"); } set_ip(); } static void set_ip(void) { set_if("e0", para_manage_read_ip(), para_manage_read_gateway(), para_manage_read_mask()); set_dns(para_manage_read_dns()); } /** * @brief 更新服务器信息 */ void udp_socket_update_server_info(void) { _server_addr.sin_family = AF_INET; _server_addr.sin_port = htons(para_manage_read_server_port()); struct hostent *host; host = (struct hostent *)gethostbyname(para_manage_read_server_ip()); _server_addr.sin_addr = *((struct in_addr *)host->h_addr); rt_memset(&(_server_addr.sin_zero), 0, sizeof(_server_addr.sin_zero)); } static void bind_socket(void) { struct sockaddr_in local_addr; // 创建socket if ((_socket = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { log_w(_log_item, "socket errorn"); // todo return; } // 初始化本地地址 local_addr.sin_family = AF_INET; local_addr.sin_port = htons(para_manage_read_port()); local_addr.sin_addr.s_addr = INADDR_ANY; rt_memset(&(local_addr.sin_zero), 0, sizeof(local_addr.sin_zero)); // 绑定端口 if (bind(_socket, (struct sockaddr *)&local_addr, sizeof(struct sockaddr)) == -1) { log_w(_log_item, "Bind errorn"); // todo return; } thread_delay(STARTUP_WAIT_TIME); _is_net_work = true; } static void socket_rx(void) { rt_uint32_t addr_len; addr_len = sizeof(struct sockaddr); while (1) { _udp_socket_rx.buffer.len = recvfrom(_socket, _udp_socket_rx.buffer.buf, LEN_BUFFER_LARGE - 1, 0, (struct sockaddr *)&_udp_socket_rx.sockaddr, &addr_len); if (is_frame_valid()) { log_i(_log_item, "udp rx ip:%s port:%02dn", inet_ntoa(_udp_socket_rx.sockaddr.sin_addr.s_addr), ntohs(_udp_socket_rx.sockaddr.sin_port)); if (_udp_socket_rx.buffer.buf[PTH_DST_DEVICE_POS] == DEVICE_STATION) { // 发送给本机 send_mailbox(); } else { // 转发 uart_tx(_udp_socket_rx.buffer.buf[PTH_ADDITIONAL_POS], _udp_socket_rx.buffer.buf, _udp_socket_rx.buffer.len); // 保存配置服务器信息 if (_udp_socket_rx.buffer.buf[PTH_DST_DEVICE_POS] == DEVICE_TIME_MODULE || _udp_socket_rx.buffer.buf[PTH_DST_DEVICE_POS] == DEVICE_RADIO_MODULE) { _config_server_addr = _udp_socket_rx.sockaddr; _last_config_frame_time = get_local_time(); } }
上一篇:配置rt-thread中的lwip模块
下一篇:设计单片机日志系统
推荐阅读
史海拾趣
随着公司规模的扩大和市场份额的提升,DCCOM开始注重品牌建设和市场推广。公司投入大量资金进行品牌宣传和市场推广,通过参加各种行业展会、举办技术研讨会等方式提高品牌知名度和影响力。这些举措使得DCCOM的品牌价值得到了显著提升。
DCCOM公司自创立之初,就注重技术创新和研发投入。在成立初期,公司研发团队成功开发出一种具有高性能和低功耗特点的电子元件,这一创新技术迅速赢得了市场的认可。随着技术的不断迭代和升级,DCCOM逐渐在电子元件市场上占据了一席之地。
Bellnix Co Ltd自创立之初,便以技术创新为核心竞争力。在电子元器件制造领域,公司不断投入研发,推出了一系列高性能、低成本的芯片产品。这些产品不仅在国内市场占据了一席之地,还成功打入了国际市场,赢得了众多客户的认可。随着技术的不断积累,Bellnix逐渐在行业内树立起了技术领先的形象,从而实现了公司的快速发展。
在市场竞争日益激烈的背景下,川晶科技始终坚持创新驱动的发展战略。公司不断加大产品创新和自主研发的力度,推动产品向微型化、低耗能方向发展。通过引入新技术、新工艺,川晶科技成功开发出了一系列具有竞争力的新产品,满足了市场的多样化需求。同时,公司还积极探索新的应用领域,努力拓展市场空间,为公司的持续发展注入了新的动力。
TT50短信透明收发模块特点 ●无需用户掌握GSM和SMS方面的知识,无需复杂编程,无需编码转换,通过串口透明收发中英文手机短信。 短时间内开发出稳定、可靠的基于GSM手机短信通讯的设备。 ...… 查看全部问答∨ |
|
针对动力线(三相)、讯号线、IO线、特殊电源线简介 共通点: 线材本身就是阻抗体,为何电线会发烫发热?为何会有压降?为何会耗电? 都是电阻造成的。此阻抗来自何处? 1、 自身材料(金、银、铜、铝、锡) 传输系数(导电率)—金最佳、最贵 ...… 查看全部问答∨ |
本帖最后由 paulhyde 于 2014-9-15 04:17 编辑 关于LM358的资料 Lm358内部包括两个独立的、高增益、内部频率补偿的双运算放大器,适合于电源电压范围很宽的单电源使用,也适用于双电源工作模式,再推荐工作条件下,电源电流与电源电压无关,它的 ...… 查看全部问答∨ |
导航电子地图众所周知为GPS导航的核心和根本,导航地图更新和升级乃是导航地图生命线,甚至是GPS导航产品存活的标准。我国GPS导航市场经过几年的发展,现在关于导航地图的升级问题越来越来严重,成为导航电子地图商的一大难题。 &nbs ...… 查看全部问答∨ |
如何实现FAT配置注册表实现自动化分区功能,因为我的EBOOT没有分区功能,但又想实现HIVE-BASE+FAT? 环境:S3C2410+NAND(64)+RAM(64)… 查看全部问答∨ |
关于LQFP144的STM32,可以画成2层板吗? 1。我参考一些开发板,大都是4层的,当然它板子尺寸比较小,而且采用0603封装。 我问做产品的,也是4层,抗干扰。 2。但是我的板子由于接插件较多,所以板子尺寸为200*250mm, 电路也不是很复杂,所 ...… 查看全部问答∨ |
5分钟点击一次保存,每次工作项目文件夹做两次备份!不管是软件设计还是硬件设计,还是神马的,反正打开软件了就得养成良好习惯5分钟点一次保存,最好一闲下来手痒就点保存,保存,另存,存~~~~~~~~~~~~~~~~~~… 查看全部问答∨ |