CH9121網路串列埠透傳模組STM32驅動
阿新 • • 發佈:2022-02-07
CH9121串列埠轉乙太網模組STM32驅動
目錄0. 簡介
CH9121 整合TCP/IP 協議棧,可實現網路資料包和串列埠資料的雙向透明傳輸,具有TCPCLIENT、TCP SERVER、UDP 3 種工作模式,串列埠波特率最高可支援到921600bps,可通過上位機軟體輕鬆配置,方便快捷。
下圖為CH9121 應用框圖:
1. 特性:
內部自帶乙太網介質傳輸層(MAC)和物理層(PHY)。
實現串列埠資料和網路資料的雙向透明傳輸。
支援10/100M,全雙工/半雙工自適應乙太網介面,相容IEEE 802.3 協議。
支援MDI/MDIX 線路自動轉換。
工作模式支援TCP CLIENT、TCP SERVER 和UDP 模式。
串列埠波特率支援300bps ~ 921600bps。
串列埠TTL 電平,相容3.3V 和5V。
串列埠支援全雙工和半雙工串列埠通訊,支援RS485 收發自動切換。
工作模式、埠、IP 等網路引數,串列埠波特率等引數可通過上位機配置。
支援虛擬串列埠。
2. 應用場合
3. 示例平臺
STM32F407
4. 程式碼
bsp_ch9121.h
// 定義了與網路CH9121通訊的基本資料結構,和配置結構,引數等 #ifndef __BSP_CH9121_H__ #define __BSP_CH9121_H__ #include <bsp.h> // 本程式中預設模組做為客戶端 #define M_UARTX UART4 #define WRITE_CMD {Usartx_SendByte(M_UARTX, 0x57);Usartx_SendByte(M_UARTX, 0xab);} // 定義接收和傳送緩衝區,用動態申請大小,打包長度小於1024byte extern uint8_t net_tx_buf[1024]; extern uint8_t net_rx_buf[1024]; extern uint8_t overflow_flag; // 網路連線狀態型別 typedef enum _ConnectStatus { disconnect = 0, connect_ok } ConnectStatus; // 校驗方式資料型別 typedef enum _Serial_Check { Even_Check = 0, Odd_Check, Mark, Space, None } Serial_Check; // 工作模式型別 typedef enum _Net_Mode { TCP_Server_mode = 0, TCP_Client_mode, UDP_Server_mode, UDP_Client_mode } Net_Mode; // 伺服器/客戶端通訊相關的型別 typedef struct _Net_CommunitionType { uint16_t port_num; // 埠號 uint8_t ip_address[4]; // IP地址 uint8_t subnet_mask[4]; // 子網掩碼 uint8_t gateway[4]; // 預設閘道器 uint16_t tcp_retry_count; // TCP重試次數 uint8_t mac_address[4]; // MAC地址 ConnectStatus status; // 連線狀態 Net_Mode net_mode; } Net_CommunitionType; extern Net_CommunitionType net_communition_Client; extern Net_CommunitionType net_communition_DstServer; extern Net_CommunitionType net_communition_Server1; // 串列埠相關資料型別 typedef struct _Serial { uint32_t bound; // 波特率 Serial_Check serial_check; // 校驗型別 uint8_t data_bit; // 資料位數 uint8_t stop_bit; // 停止位 uint32_t timeout; // 超時時間 } Serial; extern Serial serial; // 寫命令碼,格式(0x57 0xab + 命令碼 + 資料) #define RESET_CHIP 0x02 // 復位命令,晶片重新執行 #define UPDATE_CONFIG 0x0d // 更新配置引數至 EEPROM #define CMD_EXECUTION 0x0e // 命令執行 #define SET_CHIP_MODE 0x10 // 設定模式 #define SET_CHIP_IP 0x11 // 設定晶片 IP 地址 #define SET_CHIP_SUBNET_MASK 0x12 // 設定晶片掩碼 #define SET_CHIP_GATEWAY 0x13 // 設定晶片閘道器 #define SET_LOCAL_PORT 0x14 // 設定晶片本地埠 #define SET_DESTINATION_IP 0x15 // 設定晶片目的 IP 地址 #define SET_DESTINATION_PORT 0x16 // 設定晶片目的埠 #define SET_SERIAL_BOUND 0x21 // 設定串列埠波特率 #define SET_SERIAL_DATA_FORMAT 0x22 // 設定串列埠校驗位資料位停止位 #define EXIT_SERIAL_CONFIG 0x5e // 退出串列埠配置模式 // 讀命令碼,格式(0x57 0xab + 命令碼) #define READ_CHIP_MODE 0x60 // 讀取晶片工作模式,返回 1 位元組 #define READ_CHIP_IP 0x61 // 讀取晶片 IP 地址,返回 4 位元組 #define READ_CHIP_SUBNET_MASK 0x62 // 讀取晶片掩碼,返回 4 位元組 #define READ_CHIP_GATEWAY 0X63 // 讀取晶片閘道器,返回 4 位元組 #define READ_SOURCE_PORT 0x64 // 讀取晶片源埠號,返回 2 位元組 #define READ_DESTINATION_IP 0x65 // 讀取晶片目的 IP 地址,返回 4 位元組 #define READ_DESTINATION_PORT 0x66 // 讀取晶片目的埠號,返回 2 位元組 #define READ_RETRY_TIMES 0x67 // 讀取 TCP 重試次數,返回 1 位元組 #define READ_SERIAL_BOUND 0x71 // 讀取串列埠波特率,返回 4 位元組 #define READ_SERIAL_DATA_FORMAT 0x72 // 讀取串列埠校驗位資料位停止位,返回 3 位元組 #define READ_SERIAL_OVERTIME 0x73 // 讀取串列埠超時時間,返回 1 位元組 #define READ_MAC_ADDRESS 0x81 // 讀取 MAC 地址,返回 6 位元組 #define READ_TCP_STATUS 0x03 // 讀取 TCP 連線狀態(TCP CLIENT 模式下),返回 1 位元組,1:連線,0:斷開。 // 公有函式區域 void init_ch9121(void); void send_netdata(uint8_t * t_buf); uint8_t read_WorkMode(void); uint16_t read_source_port(void); void read_chip_ip(uint8_t *ip_addr); uint16_t read_distination_port(void); void read_distination_ip(uint8_t *ip_addr); void reset_chip(void); #endif
bsp_ch9121.c
#include <bsp_ch9121.h> // 備註:兩個讀函式之間間隔510ms // 定義接收和傳送緩衝區,用動態申請大小 uint8_t net_tx_buf[1024]; uint8_t net_rx_buf[1024]; // 溢位標誌 uint16_t overflow = 0; uint8_t overflow_flag = 0; // 模組串列埠引數初始化 Serial serial = { 921600, None, 0x08, 0x01, 0 }; // 模組客戶端結構體成員初始化 Net_CommunitionType net_communition_Client = { 2000, // 客戶端埠號 {192, 168, 1, 200}, // 客戶端ip地址 {255, 255, 255, 0}, // 客戶端子網掩碼 {192, 168, 1, 1}, // 客戶端預設閘道器 }; // 模組做伺服器端結構體成員 Net_CommunitionType net_communition_Server1 = { 2001, // 伺服器埠號 {192, 168, 1, 202}, // 伺服器ip地址 {255, 255, 255, 0}, // 伺服器子網掩碼 {192, 168, 1, 1}, // 服霧器預設閘道器 }; // 如果模組用TCP client模式,這裡的引數自行修改為目的伺服器對應引數 Net_CommunitionType net_communition_DstServer = { 1000, // 伺服器埠號 {192, 168, 1, 125}, // 伺服器ip地址 {255, 255, 255, 0}, // 伺服器子網掩碼 {192, 168, 1, 1}, // 服霧器預設閘道器 }; // 進入配置模式 // 對於內部讀寫網口需要先呼叫此函式進入配置模式 static void ch9121_config_mode(void) { // 傳送命令字進入配置模式 Usartx_SendByte(M_UARTX, 0x55); Usartx_SendByte(M_UARTX, 0xaa); Usartx_SendByte(M_UARTX, 0x5a); delay_ms(100); M_UARTX->DR = 0XA5; } static void ch9121_exitconfige(void) { // 傳送命令字進入配置模式 WRITE_CMD; Usartx_SendByte(M_UARTX, EXIT_SERIAL_CONFIG); } // 更新配置引數到EEPROM static void update_config(void) { WRITE_CMD; Usartx_SendByte(M_UARTX, UPDATE_CONFIG); } // 執行配置 static void execution_config(void) { WRITE_CMD; Usartx_SendByte(M_UARTX, CMD_EXECUTION); } // 配置為晶片為TCP Server模式 static void ch9121_TCP_Server(void) { // 晶片進入配置模式 ch9121_config_mode(); delay_ms(100); // 配置為伺服器模式 WRITE_CMD; Usartx_SendByte(M_UARTX, SET_CHIP_MODE); Usartx_SendByte(M_UARTX, TCP_Server_mode); delay_ms(100); // 設定晶片IP地址 192.168.1.202 WRITE_CMD; Usartx_SendByte(M_UARTX, SET_CHIP_IP); Usartx_SendByte(M_UARTX, net_communition_Server1.ip_address[0]); Usartx_SendByte(M_UARTX, net_communition_Server1.ip_address[1]); Usartx_SendByte(M_UARTX, net_communition_Server1.ip_address[2]); Usartx_SendByte(M_UARTX, net_communition_Server1.ip_address[3]); delay_ms(100); // 設定晶片子網掩碼 255.255.255.0 WRITE_CMD; Usartx_SendByte(M_UARTX, SET_CHIP_SUBNET_MASK); Usartx_SendByte(M_UARTX, net_communition_Server1.subnet_mask[0]); Usartx_SendByte(M_UARTX, net_communition_Server1.subnet_mask[1]); Usartx_SendByte(M_UARTX, net_communition_Server1.subnet_mask[2]); Usartx_SendByte(M_UARTX, net_communition_Server1.subnet_mask[2]); delay_ms(100); // 設定晶片閘道器 192.168.1.1 WRITE_CMD; Usartx_SendByte(M_UARTX, SET_CHIP_GATEWAY); Usartx_SendByte(M_UARTX, net_communition_Server1.gateway[0]); Usartx_SendByte(M_UARTX, net_communition_Server1.gateway[1]); Usartx_SendByte(M_UARTX, net_communition_Server1.gateway[2]); Usartx_SendByte(M_UARTX, net_communition_Server1.gateway[3]); delay_ms(100); // 設定伺服器埠2001,埠號傳送位元組序是先發低位元組,再發高位元組 WRITE_CMD; Usartx_SendByte(M_UARTX, SET_LOCAL_PORT); Usartx_SendByte(M_UARTX, net_communition_Server1.port_num & 0x0ff); Usartx_SendByte(M_UARTX, (uint8_t)(net_communition_Server1.port_num>>8)); delay_ms(100); // 更新配置到EEPROM update_config(); delay_ms(100); // 執行配置 execution_config(); delay_ms(100); // 退出配置模式 ch9121_exitconfige(); } // 配置為TCP Client模式 static void ch9121_TCP_Client(void) { // 晶片進入配置模式 ch9121_config_mode(); delay_ms(100); // 配置為客戶端模式 WRITE_CMD; Usartx_SendByte(M_UARTX, SET_CHIP_MODE); Usartx_SendByte(M_UARTX, TCP_Client_mode); delay_ms(100); /* // 已從上位機軟體配置為DHCP模式,不需要配置IP、閘道器和子網掩碼,埠號配置為了隨機 // 設定晶片IP地址 192.168.1.202 WRITE_CMD; Usartx_SendByte(M_UARTX, SET_CHIP_IP); Usartx_SendByte(M_UARTX, net_communition_Client.ip_address[0]); Usartx_SendByte(M_UARTX, net_communition_Client.ip_address[1]); Usartx_SendByte(M_UARTX, net_communition_Client.ip_address[2]); Usartx_SendByte(M_UARTX, net_communition_Client.ip_address[3]); // 設定晶片子網掩碼 255.255.255.0 WRITE_CMD; Usartx_SendByte(M_UARTX, SET_CHIP_SUBNET_MASK); Usartx_SendByte(M_UARTX, net_communition_Client.subnet_mask[0]); Usartx_SendByte(M_UARTX, net_communition_Client.subnet_mask[1]); Usartx_SendByte(M_UARTX, net_communition_Client.subnet_mask[2]); Usartx_SendByte(M_UARTX, net_communition_Client.subnet_mask[2]); // 設定晶片閘道器 192.168.1.1 WRITE_CMD; Usartx_SendByte(M_UARTX, SET_CHIP_GATEWAY); Usartx_SendByte(M_UARTX, net_communition_Client.gateway[0]); Usartx_SendByte(M_UARTX, net_communition_Client.gateway[1]); Usartx_SendByte(M_UARTX, net_communition_Client.gateway[2]); Usartx_SendByte(M_UARTX, net_communition_Client.gateway[3]); // 設定伺服器埠2001,埠號傳送位元組序是先發低位元組,再發高位元組 WRITE_CMD; Usartx_SendByte(M_UARTX, SET_LOCAL_PORT); Usartx_SendByte(M_UARTX, net_communition_Client.port_num & 0x0ff); Usartx_SendByte(M_UARTX, (uint8_t)net_communition_Client.port_num>>8); */ // 設定目的伺服器IP地址 WRITE_CMD; Usartx_SendByte(M_UARTX, SET_DESTINATION_IP); Usartx_SendByte(M_UARTX, net_communition_DstServer.ip_address[0]); Usartx_SendByte(M_UARTX, net_communition_DstServer.ip_address[1]); Usartx_SendByte(M_UARTX, net_communition_DstServer.ip_address[2]); Usartx_SendByte(M_UARTX, net_communition_DstServer.ip_address[3]); delay_ms(100); // 設定目的伺服器埠1000,埠號傳送位元組序是先發低位元組,再發高位元組 WRITE_CMD; Usartx_SendByte(M_UARTX, SET_DESTINATION_PORT); Usartx_SendByte(M_UARTX, net_communition_DstServer.port_num & 0x0ff); Usartx_SendByte(M_UARTX, (uint8_t)(net_communition_DstServer.port_num>>8)); delay_ms(100); // 更新配置到EEPROM update_config(); delay_ms(100); // 執行配置 execution_config(); delay_ms(100); // 退出配置模式 ch9121_exitconfige(); } // 配置為UDP Client模式 static void ch9121_UDP(void) { // 晶片進入配置模式 ch9121_config_mode(); delay_ms(100); // 配置為UDP客戶端模式 WRITE_CMD; Usartx_SendByte(M_UARTX, SET_CHIP_MODE); Usartx_SendByte(M_UARTX, UDP_Client_mode); delay_ms(100); // 設定目的伺服器IP地址 WRITE_CMD; Usartx_SendByte(M_UARTX, SET_DESTINATION_IP); Usartx_SendByte(M_UARTX, net_communition_DstServer.ip_address[0]); Usartx_SendByte(M_UARTX, net_communition_DstServer.ip_address[1]); Usartx_SendByte(M_UARTX, net_communition_DstServer.ip_address[2]); Usartx_SendByte(M_UARTX, net_communition_DstServer.ip_address[3]); delay_ms(100); // 設定目的伺服器埠1000,埠號傳送位元組序是先發低位元組,再發高位元組 WRITE_CMD; Usartx_SendByte(M_UARTX, SET_DESTINATION_PORT); Usartx_SendByte(M_UARTX, net_communition_DstServer.port_num & 0x0ff); Usartx_SendByte(M_UARTX, (uint8_t)(net_communition_DstServer.port_num>>8)); delay_ms(100); // 更新配置到EEPROM update_config(); delay_ms(100); // 執行配置 execution_config(); delay_ms(100); // 退出配置模式 ch9121_exitconfige(); } // 配置為UDP Server模式 static void ch9121_UDP_Server(void) { // 晶片進入配置模式 ch9121_config_mode(); delay_ms(100); // 配置為UDP伺服器端模式 WRITE_CMD; Usartx_SendByte(M_UARTX, SET_CHIP_MODE); Usartx_SendByte(M_UARTX, UDP_Server_mode); delay_ms(100); // 設定目的伺服器IP地址 WRITE_CMD; Usartx_SendByte(M_UARTX, SET_DESTINATION_IP); Usartx_SendByte(M_UARTX, net_communition_DstServer.ip_address[0]); Usartx_SendByte(M_UARTX, net_communition_DstServer.ip_address[1]); Usartx_SendByte(M_UARTX, net_communition_DstServer.ip_address[2]); Usartx_SendByte(M_UARTX, net_communition_DstServer.ip_address[3]); delay_ms(100); // 設定目的伺服器埠1000,埠號傳送位元組序是先發低位元組,再發高位元組 WRITE_CMD; Usartx_SendByte(M_UARTX, SET_DESTINATION_PORT); Usartx_SendByte(M_UARTX, net_communition_DstServer.port_num & 0x0ff); Usartx_SendByte(M_UARTX, (uint8_t)(net_communition_DstServer.port_num>>8)); // 更新配置到EEPROM update_config(); delay_ms(100); // 執行配置 execution_config(); delay_ms(100); // 退出配置模式 ch9121_exitconfige(); } // 選擇ch9121的工作模式 // mode:0->TCP Server // 1->TCP Client // 2->UDP // 3->UDP Server static void ch9121_mode_select(uint8_t mode) { switch(mode) { case 0: ch9121_TCP_Server(); break; case 1: ch9121_TCP_Client(); break; case 2: ch9121_UDP(); break; case 3: ch9121_UDP_Server(); break; } } // 配置串列埠相關餐數 static void serial_config(void) { // 晶片進入配置模式 ch9121_config_mode(); delay_ms(100); // 設定串列埠波特率926100,需要籌夠4位元組,傳送位元組序是先發低位元組,再發高位元組 WRITE_CMD; Usartx_SendByte(M_UARTX, SET_SERIAL_BOUND); Usartx_SendByte(M_UARTX, serial.bound&0xff); Usartx_SendByte(M_UARTX, (serial.bound>>8)&0xff); Usartx_SendByte(M_UARTX, (serial.bound>>16)&0xff); Usartx_SendByte(M_UARTX, (serial.bound>>24)&0xff); delay_ms(100); // 設定串列埠資料幀格式,1位停止位,無校驗,8位資料位 WRITE_CMD; Usartx_SendByte(M_UARTX, SET_SERIAL_DATA_FORMAT); Usartx_SendByte(M_UARTX, serial.stop_bit); Usartx_SendByte(M_UARTX, serial.serial_check); Usartx_SendByte(M_UARTX, serial.data_bit); delay_ms(100); // 更新配置到EEPROM update_config(); delay_ms(100); // 執行配置 execution_config(); delay_ms(100); // 退出配置模式 ch9121_exitconfige(); } // 傳送資料 void send_netdata(uint8_t * t_buf) { while(*t_buf != '\0') { Usartx_SendByte(M_UARTX, *t_buf); t_buf++; } } /************************************************************************************************************************************************* 讀取相關函式 **************************************************************************************************************************************************/ // 讀取晶片工作模式,返回一個位元組 uint8_t read_WorkMode(void) { uint8_t netmode; // 每次進來先把緩衝陣列下標清零,便於取數 overflow = 0; // 晶片進入配置模式 ch9121_config_mode(); delay_ms(100); // 讀取晶片工作模式,返回一個位元組 WRITE_CMD; Usartx_SendByte(M_UARTX, READ_CHIP_MODE); delay_ms(100); // 退出配置模式 ch9121_exitconfige(); netmode = net_rx_buf[2]; printf("%d\r\n", netmode); switch(netmode) { case 0: return TCP_Server_mode; case 1: return TCP_Client_mode; case 2: return UDP_Server_mode; case 3: return UDP_Client_mode; } return 0xff; } // 讀取晶片IP void read_chip_ip(uint8_t *ip_addr) { uint8_t i; // 每次進來先把緩衝陣列下標清零,便於取數 overflow = 0; // 晶片進入配置模式 ch9121_config_mode(); delay_ms(100); // 讀取晶片工作模式,返回一個位元組 WRITE_CMD; Usartx_SendByte(M_UARTX, READ_CHIP_IP); delay_ms(100); for(i = 0; i < 4; i++) { ip_addr[i] = net_rx_buf[i+2]; } // 退出配置模式 ch9121_exitconfige(); printf("%d.%d.%d.%d\r\n", ip_addr[0],ip_addr[1],ip_addr[2],ip_addr[3]); } // 讀取源埠 uint16_t read_source_port(void) { uint16_t _port; // 每次進來先把緩衝陣列下標清零,便於取數 overflow = 0; // 晶片進入配置模式 ch9121_config_mode(); delay_ms(100); // 讀取晶片工作模式,返回一個位元組 WRITE_CMD; Usartx_SendByte(M_UARTX, READ_SOURCE_PORT); delay_ms(100); // 退出配置模式 ch9121_exitconfige(); _port = net_rx_buf[2]; _port |= (net_rx_buf[3]<<8); printf("%d\r\n", _port); return _port; } // 讀取目的IP void read_distination_ip(uint8_t *ip_addr) { uint8_t i; // 每次進來先把緩衝陣列下標清零,便於取數 overflow = 0; // 晶片進入配置模式 ch9121_config_mode(); delay_ms(100); // 讀取晶片工作模式,返回一個位元組 WRITE_CMD; Usartx_SendByte(M_UARTX, READ_DESTINATION_IP); delay_ms(100); for(i = 0; i < 4; i++) { ip_addr[i] = net_rx_buf[i+2]; } // 退出配置模式 ch9121_exitconfige(); printf("%d.%d.%d.%d\r\n", ip_addr[0],ip_addr[1],ip_addr[2],ip_addr[3]); } // 讀取目的埠 uint16_t read_distination_port(void) { uint16_t _port; // 每次進來先把緩衝陣列下標清零,便於取數 overflow = 0; // 晶片進入配置模式 ch9121_config_mode(); delay_ms(100); // 讀取晶片工作模式,返回一個位元組 WRITE_CMD; Usartx_SendByte(M_UARTX, READ_DESTINATION_PORT); delay_ms(100); // 退出配置模式 ch9121_exitconfige(); _port = net_rx_buf[2]; _port |= (net_rx_buf[3]<<8); printf("%d\r\n", _port); return _port; } // 復位晶片 void reset_chip(void) { // 晶片進入配置模式 ch9121_config_mode(); delay_ms(100); WRITE_CMD; Usartx_SendByte(M_UARTX, RESET_CHIP); delay_ms(100); // 退出配置模式 ch9121_exitconfige(); } // 初始化配置函式 void init_ch9121(void) { // 設定工作模式 ch9121_mode_select(TCP_Client_mode); } /** * @name UART4_IRQHandler * @brief 串列埠4中斷服務函式,目前用於CH9121網路通訊模組 * @param 空 * @return 空 * @DateTime 2019-7-20 */ void UART4_IRQHandler(void) { uint8_t return_val = 0; if(USART_GetITStatus( M_UARTX, USART_IT_RXNE ) != RESET) { return_val = USART_ReceiveData(M_UARTX); if(overflow > 1022) { overflow = 0; overflow_flag = 1; net_rx_buf[1023] = '\0'; } else { net_rx_buf[overflow++] = return_val; } } }
Posted By veis