STM32F407 CANopen master

来源:https://www.cnblogs.com/cariohu/archive/2022/04/27/16183113.html
-Advertisement-
Play Games

STM32F407控制CANopen從站 前面我有篇文章——CAN&CANopen,講清楚了CAN通訊是怎麼一回事,沒有舉具體的例子。這篇文章我就用一個具體的例子,讓大家更好的理解具體是怎麼用。 硬體準備:STM32F407ZGT6開發板+ IXXAT CAN卡+支持CANopen通訊的驅動器 目標 ...


 

STM32F407控制CANopen從站

 

前面我有篇文章——CAN&CANopen,講清楚了CAN通訊是怎麼一回事,沒有舉具體的例子。這篇文章我就用一個具體的例子,讓大家更好的理解具體是怎麼用。

硬體準備:STM32F407ZGT6開發板+ IXXAT CAN卡+支持CANopen通訊的驅動器

目標效果:STM32通過CAN口控制驅動器完成PPM和CSP模式的運動控制,對PPM和CSP模式沒有概念的參我的另一篇文章——我理解的運動控制系統,裡面有詳細介紹。

首先,完成STM32的基本配置,我用的cubeMX,這個弄起來快。

第一步,系統時鐘配置,註意紅框標記的地方,我的HSE是8Mhz的,根據你的開發板修改。F407支持的最高頻率是168Mhz,不可超過,關於時鐘配置的細節可以參官方的參考手冊,這裡不展開講了。

 

第二步,配置HSE為陶瓷晶振。

 

第三步,配置下載和調試介面。

 

第四步,CAN控制配置,我設置的波特率是1Mbps,這也是CAN匯流排支持的最高通訊速率。CAN匯流排上的所有設備波特率必須一樣,這是能通訊的前提,不然解出來的都是錯誤幀。還要使能CAN的接收中斷。

 

 

 

第五步,配置USART,這個是為了調試方便和接收控制命令用的。

 

使能USART的中斷

 

USART的發送和接收都是DMA傳輸,網傳接收和發送的DMA不可以同時使用,實測可以解決,DMA非常方便。

 

第六步,配置TIMER,這個是CSP模式定時發送數據用的。匯流排是168Mhz的,168-1的預分頻之後就是1Mhz,向上計數10000就是10ms。

 

需要開啟TIM6的中斷

 

 

第七步,工程配置,我用的KEIL,在工具鏈中選擇MDK-ARM,版本V5。

代碼生成配置,選擇所有已用的庫到工程。每個外設配置生成單獨的.c/.h文件,方便查看和管理。再次生產代碼前先備份。再次生成前保留用戶代碼,這個一定要選,並且還要寫在用戶代碼區,不然重生成後代碼都被刪除了。不再需要的配置再重生成代碼的時候刪除,這個可選,文件少編譯的更快。把所有沒有使用的引腳都設置為模擬模式,這樣可以減少功耗。

 

 

第八步,點擊GENERATE CODE生成代碼,然後用你的IDE打開工程。

到這裡cubeMX的配置就已經完成了,接下來就直接開始在IDE中上代碼了。

 

CAN控制器的初始化中沒有配置CAN的濾波器,這個需要我們手動配置。代碼放在can.c的void MX_CAN1_Init(void)函數中,如下:

  /* USER CODE BEGIN CAN1_Init 2 */

  CAN_FilterTypeDef sFilterConfig;    

       sFilterConfig.FilterActivation = CAN_FILTER_ENABLE;

       sFilterConfig.FilterBank = 0;

       sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;

       sFilterConfig.FilterIdHigh = 0x0000;

       sFilterConfig.FilterIdLow = 0x0000;

       sFilterConfig.FilterMaskIdHigh = 0x0000;

       sFilterConfig.FilterMaskIdLow = 0x0000;

       sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;

       sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;

       sFilterConfig.SlaveStartFilterBank = 14;

  if(HAL_CAN_ConfigFilter(&hcan1,&sFilterConfig))

       {

         Error_Handler();

       }

       HAL_CAN_ActivateNotification(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING);

  /* USER CODE END CAN1_Init 2 */

        這裡說下濾波器配置的兩種模式,一個是列表模式,一個是掩碼模式。列表模式就是ID在列表中的報文可以通過,其他的都不能通過,不在列表中的都不能通過,這個比較好理解。掩碼模式就是掩碼寄存器中對應bit為1的表示關心,報文中ID的對應bit位也必須為1;掩碼寄存器中對應bit為0的表示不關心,報文ID的對應bit位可為0或1。如現在配置的都是0x0000,表示任何ID的數據都接收,因為現在是把STM32做CANopen的master,需要接收匯流排上的所有數據。最後一行HAL_CAN_ActivateNotification是為了使能接收郵箱的中斷。

         接下來就是初始化各個外設,這裡遇到兩個坑,第一個是DMA的初始化要在使用DMA的外設之前,不然就不會成功。第二個是使能定時器中斷的時候要先停止定時器中斷,追溯源代碼發現是函數有個狀態沒複位,停止中斷的函數裡面將這個狀態複位了。這個可能與固件版本有關,我這個V1.27.0是這樣,STM32G474的庫也不需要這樣操作。USART的DMA接收我用了擴展函數HAL_UARTEx_ReceiveToIdle_DMA,這個非常方便。

/* USER CODE END SysInit */

  /* Initialize all configured peripherals */

  MX_GPIO_Init();

MX_DMA_Init();

  MX_USART1_UART_Init();

  MX_TIM6_Init();

  MX_CAN1_Init();

  /* USER CODE BEGIN 2 */

       HAL_TIM_Base_Start(&htim6);

       HAL_TIM_Base_Stop_IT(&htim6); // stop_IT function is necessary ,for reset state ,else TIMER won't work

       HAL_TIM_Base_Start_IT(&htim6);  

  __HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);

  HAL_UARTEx_ReceiveToIdle_DMA(&huart1,uart_rx_data,uart_rx_max);

       __HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);

       HAL_CAN_Start(&hcan1);

  /* USER CODE END 2 */

        到這裡,主要的配置就已經完成了,接下來就是細化各個功能函數了,不再詳細介紹,我直接把main.c的代碼全部複製到文章末尾了,可以直接複製去測試和研究。

       本文只是拋磚引玉的介紹了怎樣配置和使用STM32F407的CAN控制器,怎樣發送CAN報文去控制從站驅動器,沒有涉及到整個CANopen主站的協議。如網路管理,錯誤處理這些都沒有做,對於特定的項目我覺得可以根據需要去設計功能,不一定要實現協議的全部細節。後續有時間再弄個完整的CANopen master協議棧。關於驅動器調試和配置部分這裡沒有涉及,參見對於驅動器廠家的調試和使用說明即可。文章中比較陌生的名詞,可以參見我的另外兩篇文章­——我理解的運動控制系統和CAN&CANopen。

 CAN與CANOPEN - Let'sDoSomething - 博客園 (cnblogs.com)

我理解的運動控制系統 - Let'sDoSomething - 博客園 (cnblogs.com)

 

  1 /* USER CODE BEGIN Header */
  2 /**
  3   ******************************************************************************
  4   * @file           : main.c
  5   * @brief          : Main program body
  6   ******************************************************************************
  7   * @attention
  8   *
  9   * Copyright (c) 2022 STMicroelectronics.
 10   * All rights reserved.
 11   *
 12   * This software is licensed under terms that can be found in the LICENSE file
 13   * in the root directory of this software component.
 14   * If no LICENSE file comes with this software, it is provided AS-IS.
 15   *
 16   ******************************************************************************
 17   */
 18 /* USER CODE END Header */
 19 /* Includes ------------------------------------------------------------------*/
 20 #include "main.h"
 21 #include "can.h"
 22 #include "dma.h"
 23 #include "tim.h"
 24 #include "usart.h"
 25 #include "gpio.h"
 26 
 27 /* Private includes ----------------------------------------------------------*/
 28 /* USER CODE BEGIN Includes */
 29 #include "stdio.h"
 30 #include "string.h"
 31 /* USER CODE END Includes */
 32 
 33 /* Private typedef -----------------------------------------------------------*/
 34 /* USER CODE BEGIN PTD */
 35 
 36 /* USER CODE END PTD */
 37 
 38 /* Private define ------------------------------------------------------------*/
 39 /* USER CODE BEGIN PD */
 40 /* USER CODE END PD */
 41 
 42 /* Private macro -------------------------------------------------------------*/
 43 /* USER CODE BEGIN PM */
 44 
 45 /* USER CODE END PM */
 46 
 47 /* Private variables ---------------------------------------------------------*/
 48 
 49 /* USER CODE BEGIN PV */
 50   uint8_t testData[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07};
 51     //CAN transmit data field, 8 bytes
 52     uint8_t object_data[8]={0};
 53     //CSP mode conuts, work until CSP_num > CSP_MAX_NUM
 54     uint8_t CSP_num = 0;
 55     //csp mode max number, generate CSP_pos relatively
 56     uint8_t CSP_MAX_NUM = 61;
 57     //CSP_flag, 0 means unused/finished, 1 means CSP is working
 58     uint8_t CSP_flag = 0;
 59     //CAN transmit mailbox
 60     uint32_t TxMailBox = CAN_TX_MAILBOX0;
 61     //CAN transmit frame struct
 62     CAN_TxHeaderTypeDef TxHeader;
 63     //for CAN communication store data
 64     uint8_t RxData[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
 65     //store CAN receive data temporarily, convert byte to int used
 66     uint8_t can_Frame_DataField[4] ={0};
 67     //store CAN communication PDO data temporarily ,length could be longer/shorter ,upon PDO length
 68     uint8_t PDO_DataField[4] = {0};
 69     //CAN Receive frame struct
 70     CAN_RxHeaderTypeDef RxHeader;
 71     //CAN receive flag ,set by can_receive interrupt ,reset by other function
 72     uint8_t can_receive_flag = 0;
 73     //store uart receive data
 74     uint8_t uart_rx_data[]={0}; 
 75   //max uart receive length  
 76     uint16_t uart_rx_max = 255;
 77     //store result for ConvertInttoFourByte function
 78     uint8_t byte_value[4] = {0};
 79     //store CSP mode position points
 80     int32_t CSP_Pos[61]={0};
 81     //CSP mode acceleration, larger and faster , smaller and slower
 82     uint32_t acc = 5;
 83 
 84 /* USER CODE END PV */
 85 
 86 /* Private function prototypes -----------------------------------------------*/
 87 void SystemClock_Config(void);
 88 /* USER CODE BEGIN PFP */
 89   void CAN_sendTxMessage(uint32_t std_id,uint32_t length,uint8_t data[]);
 90     void ConvertIntTo4Byte(int32_t source);
 91     int32_t ConvertByteToInt(uint8_t *byte_source);
 92     void do_a_PPM_Motion();
 93     void do_a_CSP_Motion();
 94     void RPDO1_Mapping();
 95 
 96 /* USER CODE END PFP */
 97 
 98 /* Private user code ---------------------------------------------------------*/
 99 /* USER CODE BEGIN 0 */
100 
101 /* USER CODE END 0 */
102 
103 /**
104   * @brief  The application entry point.
105   * @retval int
106   */
107 int main(void)
108 {
109   /* USER CODE BEGIN 1 */
110 
111   /* USER CODE END 1 */
112 
113   /* MCU Configuration--------------------------------------------------------*/
114 
115   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
116   HAL_Init();
117 
118   /* USER CODE BEGIN Init */
119 
120   /* USER CODE END Init */
121 
122   /* Configure the system clock */
123   SystemClock_Config();
124 
125   /* USER CODE BEGIN SysInit */
126 
127   /* USER CODE END SysInit */
128   /* Initialize all configured peripherals */
129   MX_GPIO_Init();
130     MX_DMA_Init();
131   MX_USART1_UART_Init();
132   
133   MX_TIM6_Init();
134   MX_CAN1_Init();
135   /* USER CODE BEGIN 2 */
136     HAL_TIM_Base_Start(&htim6);
137     HAL_TIM_Base_Stop_IT(&htim6); // stop_IT function is necessary ,for reset state ,else TIMER won't work
138     HAL_TIM_Base_Start_IT(&htim6);
139     
140   __HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);
141   HAL_UARTEx_ReceiveToIdle_DMA(&huart1,uart_rx_data,uart_rx_max);
142     __HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);
143 
144     HAL_CAN_Start(&hcan1);
145 
146     HAL_Delay(50);   //delay would be necessary ,shorter time is also OK
147 
148     printf("This is CAN communication test program!\n");
149     printf("After power up!Send 1 to activate PPM mode or send 2 to CSP mode\n");
150     RPDO1_Mapping();
151     HAL_Delay(10);
152     
153   /* USER CODE END 2 */
154 
155   /* Infinite loop */
156   /* USER CODE BEGIN WHILE */
157   while (1)
158   {
159     /* USER CODE END WHILE */
160 
161     /* USER CODE BEGIN 3 */
162         HAL_Delay(500);
163         HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_3);
164 
165         if(1 == uart_rx_data[0])
166         { printf("PPM TEST\n");
167       do_a_PPM_Motion();
168       uart_rx_data[0] = 0;    
169         }
170         else if(2 == uart_rx_data[0])
171             { printf("CSP TEST\n");
172           //initiate CSP mode pos array
173           for(int i=0;i<CSP_MAX_NUM;i++)
174           { 
175                //means explanation: physic formula  S= 1/2*acc*(t*t) 
176                // S= 1/2*a*t*t  a=100, acceleration 30points ,dec 30 points
177           // Vmax= 30*a  = 30*100 = 3000        
178               if(i<=30)
179                CSP_Pos[i] = 0.5*acc*i*i; // S= 1/2*a*t*t  a=100, 
180               else
181                  CSP_Pos[i] = CSP_Pos[i-1]+acc*(CSP_MAX_NUM/2)-0.5*acc*(2*(i - CSP_MAX_NUM/2)-1);
182            }
183         do_a_CSP_Motion();    
184         uart_rx_data[0] = 0;            
185             }
186         
187   }
188   /* USER CODE END 3 */
189 }
190 
191 /**
192   * @brief System Clock Configuration
193   * @retval None
194   */
195 void SystemClock_Config(void)
196 {
197   RCC_OscInitTypeDef RCC_OscInitStruct = {0};
198   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
199 
200   /** Configure the main internal regulator output voltage
201   */
202   __HAL_RCC_PWR_CLK_ENABLE();
203   __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
204 
205   /** Initializes the RCC Oscillators according to the specified parameters
206   * in the RCC_OscInitTypeDef structure.
207   */
208   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
209   RCC_OscInitStruct.HSEState = RCC_HSE_ON;
210   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
211   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
212   RCC_OscInitStruct.PLL.PLLM = 4;
213   RCC_OscInitStruct.PLL.PLLN = 168;
214   RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
215   RCC_OscInitStruct.PLL.PLLQ = 4;
216   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
217   {
218     Error_Handler();
219   }
220 
221   /** Initializes the CPU, AHB and APB buses clocks
222   */
223   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
224                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
225   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
226   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
227   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
228   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
229 
230   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
231   {
232     Error_Handler();
233   }
234 }
235 
236 /* USER CODE BEGIN 4 */
237 void do_a_CSP_Motion()
238 {
239   //steps 1. disable motor, write 0x06 to object 0x6040
240     //      2. chang mode to CSP, write 0x08 to object 0x6060
241     //      3. check mode is CSP, read 0x6061
242     //      4. set CSP cycle-time, write 0x32 to object 0x6060,unit is ms
243     //      5. enable motor, write 0x0F to object 0x6040
244     //      6. check motor is enabled, read 0x6041
245     //      7. read current position, read 0x607A
246     //      8. CPS_Pos[]+current position as final target position
247     //      9. start remote node
248     //      10. send target position by PDO and follow SYNC command 0x80
249     //      11. CSP motion finished
250     //
251  //steps 1. disable motor, write 0x06 to object 0x6040
252             object_data[0]=0x2B;object_data[1]=0x40;object_data[2]=0x60;object_data[3]=0x00;
253             object_data[4]=0x06;object_data[5]=0x00;object_data[6]=0x00;object_data[7]=0x00;
254             can_receive_flag = 0;
255             CAN_sendTxMessage(0x601,8,object_data);
256             HAL_Delay(1); //HAL_DELAY() delay 1ms is necessary, else will stick here
257             while(1 != can_receive_flag)
258                     {;}   //HAL_DELAY() delay 1ms is necessary, else will stick here    
259     //      2. chang mode to CSP, write 0x08 to object 0x6060                
260                     object_data[0]=0x2F;object_data[1]=0x60;object_data[2]=0x60;object_data[3]=0x00;
261             object_data[4]=0x08;object_data[5]=0x00;object_data[6]=0x00;object_data[7]=0x00;
262             can_receive_flag = 0;
263             CAN_sendTxMessage(0x601,8,object_data);
264                     HAL_Delay(1);
265             while(1 != can_receive_flag)
266                     {;}    
267     //      3. check mode is CSP, read 0x6061
268                     object_data[0]=0x40;object_data[1]=0x61;object_data[2]=0x60;object_data[3]=0x00;
269             object_data[4]=0x00;object_data[5]=0x00;object_data[6]=0x00;object_data[7]=0x00;
270             can_receive_flag = 0;
271             CAN_sendTxMessage(0x601,8,object_data);
272                     HAL_Delay(1);
273             while(1 != can_receive_flag)
274                     {;}
275                     if(8 != RxData[4]) //8 means CSP mode
276                         printf("Set CSP mode failed\n");        
277 //      4. set CSP cycle-time, write 0x32 to object 0x6060,unit is ms                    
278                     object_data[0]=0x2F;object_data[1]=0xC2;object_data[2]=0x60;object_data[3]=0x00;
279             object_data[4]=0x32;object_data[5]=0x00;object_data[6]=0x00;object_data[7]=0x00;
280             can_receive_flag = 0;
281             CAN_sendTxMessage(0x601,8,object_data);
282                     HAL_Delay(1);
283             while(1 != can_receive_flag)
284                     {;}        
285 //      5. enable motor, write 0x0F to object 0x6040
286                     object_data[0]=0x2B;object_data[1]=0x40;object_data[2]=0x60;object_data[3]=0x00;
287             object_data[4]=0x0F;object_data[5]=0x00;object_data[6]=0x00;object_data[7]=0x00;
288             can_receive_flag = 0;
289             CAN_sendTxMessage(0x601,8,object_data);
290                     HAL_Delay(1);
291             while(1 != can_receive_flag)
292                     {;}
293 //      6. check motor is enabled, read 0x6041                    
294                     object_data[0]=0x40;object_data[1]=0x41;object_data[2]=0x60;object_data[3]=0x00;
	   

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 聽說Docker這玩意挺長時間了,新建Web應用的時候,也註意到有個啟用Docker的選項。 前兩天掃了一眼《【大話雲原生】煮餃子與docker、kubernetes之間的關係》,覺得有點意思,決定試試Docker。 然後被坑、百度... 現將整個過程記錄一下 一、新建項目 點擊創建,被通知“需要安 ...
  • 前言 本文主要介紹ArcGis的ArcEngine開發,學習時,我們需要放下心裡障礙,那就是Gis開發只是普通的軟體開發,並不需要專業的GIS知識,就是非常普通的,調用相關的C++開發的COM組件。 開發環境:VS2017。 ArcEngine版本:10.1。 基礎學習 正式使用ArcGis之前,需 ...
  • Masa Blazor是什麼 在此之前我們已經介紹過什麼是Masa Blazor,以及如何使用Masa Blazor,如果還有不瞭解Masa Blazor的同學可以看我上篇文章【初識Masa Blazor】。那麼今天就帶大家探索一下如何在MAUI中使用Masa Blazor,那麼我們先來瞭解一下什麼 ...
  • 理解依賴項屬性 依賴項屬性是專門為WPF創建的,在WPF的核心特征中使用。 創建依賴項屬性 public class DP: DependencyObject { //聲明依賴項屬性 public static readonly DependencyProperty MydpProperty; st ...
  • Set介面 介紹 無序(添加和取出的順序不一致),沒有索引 不允許重覆,所以最多包含一個null JDK API中Set介面實現類有 Set介面常用方法 和List介面一樣,Set介面也是Collection的子介面,因此,常用方法和Collection介面一樣 特點 不能存放重覆的元素 set介面 ...
  • 最新 x86_64 系統調用入口分析 (基於5.7.0) 整體概覽 最近的工作涉及系統調用入口,但網上的一些分析都比較老了,這裡把自己的分析過程記錄一下,僅供參考。 x86_64位系統調用使用 SYSCALL 指令進入內核空間,使CPU切換到ring 0。SYSCALL 指令主要工作為從MSR寄存器 ...
  • 鏡像下載、功能變數名稱解析、時間同步請點擊 阿裡雲開源鏡像站 基礎安裝 一:製作安裝介質 下載ISO鏡像文件: https://archlinux.org/download/ # 官方下載網址 在linux系統中可以用pgp驗證系統簽名: gpg --keyserver-options auto-key-r ...
  • 鏡像下載、功能變數名稱解析、時間同步請點擊 阿裡雲開源鏡像站 寫在前面可參考 PS:使用wsl2作為Windows下Ubuntu環境時提升代碼編譯等效率的幾個點: 1.安裝完wsl後,檢查wsl的版本,確保是版本2(cmd執行wsl -l -v查看,如果不是,可通過wsl.exe -set-version ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...