for (int i = 0; i <= timer; i++) { int readLength = i == timer ? item.Length - 100 * i : 100; byte[] Res = CommonMethods.objMod.ReadOutputStatus(CommonMethods.Address, StartAddress+100*i, readLength); if (Res != null) //从站地址 //起始地址 //读取长度 { ErrorTimer = 0; ByteList.AddRange(Res); } else { ErrorTimer += 1; } } 以上代码是什么意思?给我用通俗的语言解释清楚

时间: 2025-03-20 21:02:53 浏览: 22
### C#代码功能与逻辑解析 以下是关于 `for` 循环中通过 `ReadOutputStatus` 方法读取字节数组并处理结果的详细分析: #### 功能概述 该段代码的主要目的是通过多次调用 `ReadOutputStatus` 方法来获取一系列字节数组,并对这些字节数组进行进一步处理。具体来说,它可能涉及从某种外部设备或接口读取数据流,并将接收到的数据逐步存储或转换为其他形式。 --- #### 代码结构与意义 假设代码如下所示(基于上下文推测): ```csharp byte[] outputData; for (int i = 0; i < numberOfIterations; i++) { outputData = ReadOutputStatus(); // 对outputData进行后续操作 } ``` 1. **变量声明** - 定义了一个名为 `outputData` 的字节数组变量用于存储每次调用 `ReadOutputStatus` 返回的结果[^1]。 2. **循环控制** - 使用 `for` 循环执行固定次数的操作,其中 `numberOfIterations` 表示需要重复调用 `ReadOutputStatus` 的总次数。 - 这种设计通常适用于已知需要连续读取多个数据包的情况。 3. **核心方法:`ReadOutputStatus`** - 调用了 `ReadOutputStatus` 方法,其返回值是一个字节数组。 - 基于引用描述,可以推断此方法可能是为了从某个硬件设备、网络连接或其他输入源读取原始数据[^2]。 4. **后续处理** - 注释部分提到 “对 `outputData` 进行后续操作”,这表明在实际应用中可能会有额外的逻辑来解析或转化这个字节数组的内容。 - 可能会涉及到的方法包括但不限于截取特定范围内的子数组 或者将整个字节数组反序列化回复杂对象[^4]。 --- #### 示例扩展说明 如果要实现更具体的场景,则可以根据需求加入更多细节。例如: - 如果目标是从 MySQL 数据库提取记录并将它们存入内存中的集合类实例里,则可参照以下伪码片段[^5]: ```csharp List<Customer> customers = new List<Customer>(); while (rst.Next()) { Customer customer = new Customer( rst.GetString("id"), rst.GetString("name"), rst.GetString("address"), rst.GetDouble("salary")); customers.Add(customer); } ``` - 若需利用 `.Skip()` 和 `.Take()` 来选取指定位置上的若干个元素作为新数组的一部分时,也可以这样写: ```csharp byte[] subArray = byteArray.Skip(startIndex).Take(length).ToArray(); ``` --- #### 总结 综上所述,在给定条件下,“对于每一次迭代都去请求一次状态输出”的行为模式实际上就是不断累积来自外界的信息直到满足预定条件为止的过程。这种技术广泛应用于实时监控系统或者批量下载文件等领域之中。 ---
阅读全文

相关推荐

private void ResultHandle() { Set_ProcessControl_Timer(0, false); SSS_Debug(21); mTotalRunTime = DateTime.Now.Ticks - mTotalRunTime; label_timeused_counter.Text = (mTotalRunTime / 10000000).ToString("N2") + LanguageHelper.LocRM.GetString("second"); string time = DateTime.Now.ToString();//获取当前系统时间 完整的日期和时间 stoptime = DateTime.Now; mNowStopRunTestTime = time; string tList = ""; string tList2 = "";//添加到TotalResult tList += "条码,检验工作台编号,通过检验,是否维修,起始时间,终止时间,NG信息,NG细节"; tList2 += "条码,检验工作台编号,通过检验,是否维修,起始时间,终止时间,NG信息,NG细节,MAC地址"; string tDataList = ""; string tDataList2 = ""; //int tmpCnt = 0; string res = null; string res_index = string.Empty; try { for (int i = 0; i < dt_Group.Columns.Count; i++) { if (dt_Group.Rows[0][i].ToString() != "OK") { res += dt_Group.Columns[i].ColumnName + ":" + dt_Group.Rows[0][i].ToString() + "\r\n"; res_index += i.ToString() + ","; mNgDatas += dt_Group.Columns[i].ColumnName + ","; mNowIsPassedFlag = "NG"; } } if (mNgDatas != null && mNgDatas != "") mNgDatas = mNgDatas.TrimEnd(','); if (res_index != null && res_index != "") res_index = res_index.TrimEnd(','); if (passTheTest) { mNowIsPassedFlag = "人工中断"; } tDataList += "'" + mNowBarcodeValue + "',"; //条码 tDataList += "'" + mainform.mWorkGroupID + "',";//group tDataList += "'" + mNowIsPassedFlag + "',";//通过? tDataList += "'" + mNeedRepaired + "',";//维修? tDataList += "'" + mNowStartRunTestTime + "',";//起始测试时间 tDataList += "'" + mNowStopRunTestTime + "',";//终止测试时间 tDataList += "'" + mNgDatas + "',";//ng信息 tDataList += "'" + mNgDetail + "'";//ng细节 tDataList2 += "'" + mNowBarcodeValue + "',"; //条码 tDat

//接收数据自动触发 private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) { SerialPort sp = (SerialPort)sender; byte[] buffer = new byte[sp.BytesToRead]; int bytesRead = sp.Read(buffer, 0, buffer.Length); // 将新接收的数据追加到receivedData数组 if (receivedDataLength + bytesRead <= receivedData.Length) { Array.Copy(buffer, 0, receivedData, receivedDataLength, bytesRead); receivedDataLength += bytesRead; // 检查是否接收到完整的数据包 while (receivedDataLength >= 5) { int expectedPacketLength = 6; // Head + Device + length + Command + data + Checksum if (receivedDataLength < expectedPacketLength) { break; // 等待更多的数据 } // 将字节数组转换为十六进制字符串 string hexString = BitConverter.ToString(receivedData, 0, expectedPacketLength).Replace("-", " "); // 校验和验证 byte checksum = 0; for (int i = 0; i < expectedPacketLength - 1; i++) // 不包含最后一个字节 { checksum ^= receivedData[i]; } // 将校验和转换为16进制字符串 string checksumHex = checksum.ToString("X2"); AppendTextToInfoBox($"checksum:{checksumHex}", txtInfo); byte receivedChecksum = receivedData[expectedPacketLength - 1]; // 同样将接收到的校验和转换为16进制字符串 string receivedChecksumHex = receivedChecksum.ToString("X2"); if (checksum == receivedChecksum) { //string hexString = BitConverter.ToString(receivedData, 0, expectedPacketLength).Replace("-", " "); AppendTextToInfoBox($"[{DateTime.Now:HH:mm:ss}] Received Data:\r\n {hexString}\r\n", txtInfo); // 更新UI this.Invoke((MethodInvoker)delegate { //AppendTextToInfoBox($"[{DateTime.Now:HH:mm:ss}] Complete Packet:\r\n {hexString}\r\n", txtInfo); // 对Command进行位分析 byte fourthByte = receivedData[3]; for (int i = 7; i >= 0; i--) { bool isSet = (fourthByte & (1 << i)) != 0; txtInfo.AppendText($"Bit {i}: {(isSet ? '1' : '0')}\r\n"); } }); } else { this.Invoke((MethodInvoker)delegate { txtInfo.AppendText("Checksum error.\r\n"); //AppendTextToInfoBox($"[{DateTime.Now:HH:mm:ss}] Received Data:\r\n {hexString}\r\n", txtInfo); }); } // 移动剩余的数据并调整receivedDataLength Array.Copy(receivedData, expectedPacketLength, receivedData, 0, receivedDataLength - expectedPacketLength); receivedDataLength -= expectedPacketLength; } } else { //Console.WriteLine("接收数据超出缓冲区大小"); } }三、通讯时序要求 应答超时时间5ms 在接收代码的基础上加上一个接收超时时间

import java.io.*; import java.awt.*; import javax.swing.*; import java.util.List; import java.util.ArrayList; public class Recite extends JFrame{ JLabel lblWord = new JLabel("word"); JLabel lblMeaning = new JLabel("meaning"); public void init() { setSize( 400,100 ); setLayout(new FlowLayout()); getContentPane().add(lblWord); getContentPane().add(lblMeaning); setDefaultCloseOperation(EXIT_ON_CLOSE); setVisible(true); } List<String> words = new ArrayList<>(); List<String> meanings = new ArrayList<>(); int current = 0; public void start() { new Thread(()->{ try{ readAll(); }catch(IOException ex){} new javax.swing.Timer(1000,(e)->{ lblWord.setText( words.get(current) ); lblMeaning.setText( meanings.get(current) ); current++; }).start(); }).start(); } public void readAll( ) throws IOException{ String fileName = "College_Grade4.txt"; String charset = "GB2312"; BufferedReader reader = new BufferedReader( new InputStreamReader( new FileInputStream(fileName), charset)); String line; while ((line = reader.readLine()) != null) { line = line.trim(); if( line.length() == 0 ) continue; int idx = line.indexOf("\t"); words.add( line.substring(0, idx )); meanings.add( line.substring(idx+1)); } reader.close(); } public static void main( String[] args){ Recite f = new Recite(); f.init(); f.start(); }}界面可以再好看一点;可以去掉音标;可以改变单词显示的速度;可以增加标记生词并记到生词本中;可以增加测试的功能(单词含义可以随机选4个词的含义来让用户选择)等等。附件中有两个代码,一个单词本。

[I/drv.emac] link down etharp_timer etharp_request: sending ARP request. pbuf_alloc(length=28) pbuf_alloc(length=28) == 0x2400d438 etharp_raw: sending raw ARP packet. pbuf_add_header: old 0x2400d458 new 0x2400d44a (14) ethernet_output: sending packet 0x2400d438 [W/drv.emac] eth transmit frame faild: 18 pbuf_free(0x2400d438) pbuf_free: deallocating 0x2400d438 etharp_timer [I/drv.emac] link down etharp_timer etharp_timer etharp_timer etharp_timer etharp_timer etharp_request: sending ARP request. pbuf_alloc(length=28) pbuf_alloc(length=28) == 0x2400d438 etharp_raw: sending raw ARP packet. pbuf_add_header: old 0x2400d458 new 0x2400d44a (14) ethernet_output: sending packet 0x2400d438 [W/drv.emac] eth transmit frame faild: 18 pbuf_free(0x2400d438) pbuf_free: deallocating 0x2400d438 etharp_timer [I/drv.emac] link down etharp_timer etharp_timer etharp_request: sending ARP request. pbuf_alloc(length=28) pbuf_alloc(length=28) == 0x2400d438 etharp_raw: sending raw ARP packet. pbuf_add_header: old 0x2400d458 new 0x2400d44a (14) ethernet_output: sending packet 0x2400d438 [W/drv.emac] eth transmit frame faild: 18 pbuf_free(0x2400d438) pbuf_free: deallocating 0x2400d438 etharp_timer [I/drv.emac] link down etharp_timer etharp_request: sending ARP request. pbuf_alloc(length=28) pbuf_alloc(length=28) == 0x2400d438 etharp_raw: sending raw ARP packet. pbuf_add_header: old 0x2400d458 new 0x2400d44a (14) ethernet_output: sending packet 0x2400d438 [W/drv.emac] eth transmit frame faild: 18 pbuf_free(0x2400d438) pbuf_free: deallocating 0x2400d438 etharp_timer [I/drv.emac] link down etharp_timer etharp_timer etharp_timer etharp_request: sending ARP request. pbuf_alloc(length=28) pbuf_alloc(length=28) == 0x2400d438 etharp_raw: sending raw ARP packet. pbuf_add_header: old 0x2400d458 new 0x2400d44a (14) ethernet_output: sending packet 0x2400d438 [W/drv.emac] eth transmit frame faild: 18 pbuf_free(0x2400d438) stm32h743+rtthread5.2.0+lwip+lan8720 以太网闪烁

void TestDelay(uint32 delay); void TestDelay(uint32 delay) { static volatile uint32 DelayTimer = 0; while (DelayTimer<delay) { DelayTimer++; } DelayTimer=0; } extern void CAN2_ORED_0_31_MB_IRQHandler(void); #if 1 // #include "Can_Ipw.h" #define MSG_ID 20u #define RX_MB_IDX 1U #define TX_MB_IDX 0U volatile int exit_code = 0; extern Flexcan_Ip_StateType Can_Ipw_xStatus0; /* User includes / uint8 dummyData[8] = {1,2,3,4,5,6,7}; /! \brief The main function for the project. \details The startup initialization sequence is the following: * - startup asm routine * - main() / //extern const Clock_Ip_ClockConfigType Clock_Ip_aClockConfig[1]; extern void CAN0_ORED_0_31_MB_IRQHandler(void); int main(void) { uint8 u8TimeOut = 100U; CanIf_bTxFlag = FALSE; CanIf_bRxFlag = FALSE; / Initialize the Mcu driver / #if (MCU_PRECOMPILE_SUPPORT == STD_ON) Mcu_Init(NULL_PTR); #elif (MCU_PRECOMPILE_SUPPORT == STD_OFF) Mcu_Init(&Mcu_Config); / Initialize the clock tree and apply PLL as system clock / Mcu_InitClock(McuClockSettingConfig_0); while ( MCU_PLL_LOCKED != Mcu_GetPllStatus() ) { / Busy wait until the System PLL is locked / } #endif / (MCU_PRECOMPILE_SUPPORT == STD_ON) / / Write your code here / Mcu_DistributePllClock(); Mcu_SetMode(McuModeSettingConf_0); / Initialize Platform driver */ Platform_Init(NULL_PTR); Port_Init(&Port_Config); Spi_Init(&Spi_Config); #if 1 // CanTrcv_TJA1145_Init(); uint8 SWK_WUF_Detection = 0u; uint8 tempRegVal = 0u; /SBC mode StandBy/ /SBC_SetMode(CANTRCV_TRCVMODE_STANDBY);/ /Disable wakepin/ Sbc_Reg_Write(CanTrcv_Tja1145_Wpe, 0x00, FALSE); /Set Lock control register/ Sbc_Reg_Write(CanTrcv_Tja1145_Lc, 0x00, FALSE); /Can baudrate config/ Sbc_Reg_Write(CanTrcv_Tja1145_Dr, CANTRCV_TJA1145_CAN_DATA_RATE, FALSE); /Set CAN control register/ Sbc_Reg_Write(CanTrcv_Tja1145_Cc, 0x31, FALSE); Sbc_Reg_Read(CanTrcv_Tja1145_Ts, &tempRegVal); Sbc_Reg_Read(CanTrcv_Tja1145_Tes, &SWK_WUF_Detection); Sbc_Reg_Write(CanTrcv_Tja1145_Mc, CanTrcv_Tja1145_Mc_MC_Normal, FALSE); Sbc_Reg_Write(CanTrcv_Tja1145_Cc,CanTrcv_Tja1145_Cc_CMC_Active,FALSE); #endif // Clock_Ip_Init(&Clock_Ip_aClockConfig[0]); volatile Flexcan_Ip_StatusType result = 1; volatile Flexcan_Ip_StatusType result1 = 1; IntCtrl_Ip_EnableIrq(FlexCAN0_1_IRQn); IntCtrl_Ip_InstallHandler(FlexCAN0_1_IRQn, CAN0_ORED_0_31_MB_IRQHandler, NULL_PTR); // Dio_WriteChannel(DioConf_DioChannel_DioChannel_O_S_STB_CAN3_M, STD_LOW);//CAN3 STB Flexcan_Ip_DataInfoType rx_info = { .msg_id_type = FLEXCAN_MSG_ID_STD, .data_length = 8u, .is_polling = TRUE, .is_remote = FALSE }; Flexcan_Ip_MsgBuffType rxData; FlexCAN_Ip_Init(CanController_0, &Can_Ipw_xStatus0, &Flexcan_aCtrlConfigPB[0U]);// while (1) { if(rx_compli==1) { FlexCAN_Ip_SetStartMode(CanController_0); FlexCAN_Ip_ConfigRxMb(CanController_0, RX_MB_IDX, &rx_info, MSG_ID); // rx_info.is_polling = FALSE; FlexCAN_Ip_Send(CanController_0, TX_MB_IDX, &rx_info, MSG_ID, (uint8 *)&dummyData); FlexCAN_Ip_Receive(CanController_0, RX_MB_IDX, &rxData, TRUE); while(FlexCAN_Ip_GetTransferStatus(CanController_0, RX_MB_IDX)

如果同一上位机通过ttl同样的方式向下面两个串口写入相同数据写入后有什么区别#include “main.h” uint8_t uart2_rx_over_time; uint8_t uart2_rx_time_start; uint8_t uart2_rx_finish_ifg; uint8_t *uart2_tx_p; //UART发送指针 uint16_t uart2_rx_len=0; uint16_t uart2_tx_len; uint8 Rx2_Frame[URRT2_RX_SIZE]; uint8 Tx2_Frame[URRT2_TX_SIZE]; //uart2 开启超时判断 void uart2_start_time(void) { uart2_rx_over_time=50; //5mS超时判断 超过10ms未接收到数据表示接收完成 放在滴答中断中0.1ms uart2_rx_time_start=1; } //判断串口是否接收完成 void uart_rx_finish_check(void) { if(uart2_rx_time_start==1) { if(uart2_rx_over_time>0) { uart2_rx_over_time–; } else { uart2_rx_finish_ifg =1; uart2_rx_time_start =0; } } } /************************************************ 函数名称 : USART_GPIO_Configuration 功 能 : USART所使用管脚输出输入定义 参 数 : 无 OUT通用输出模式 IN输入模式 AF复用功能模式 AN模拟模式 PP复用推挽 OD复用开漏 UP上拉 down下拉 nopull浮空 *************************************************/ void USART2_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA,ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE); GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_1); GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_1); //定义USART TX_RX 引脚为复用输出 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, &GPIO_InitStructure); //Usart1 NVIC 配置 NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; //IRQ通道:串口1 NVIC_InitStructure.NVIC_IRQChannelPriority = 0; //优先级 :1级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能IRQ通道 NVIC_Init(&NVIC_InitStructure); //USART 初始化设置 USART_InitStructure.USART_BaudRate = 2400<<(prd_info.baud_rate-1); //设定传输速率 USART_InitStructure.USART_WordLength = (prd_info.Parity==0)?USART_WordLength_8b:USART_WordLength_9b; //设定传输数据位数 USART_InitStructure.USART_StopBits = USART_StopBits_1; //设定停止位个数 USART_InitStructure.USART_Parity = (prd_info.Parity==0)?(USART_Parity_No):((prd_info.Parity>1)?(USART_Parity_Even):(USART_Parity_Odd)); //不用校验位 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //不用流量控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //使用接收和发送功能 USART_Init(USART2, &USART_InitStructure); //初始化USART1 USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); //使能USART1接收中断 USART_Cmd(USART2, ENABLE); } void RS485_SendByte(uint8 Data) { USART2->TDR = (Data & (uint16_t)0x01FF); while((USART2->ISR & USART_FLAG_TC) == RESET); } /************************************************ 函数名称 : RS485_Send_Data 功 能 : 串口1 RS485发送N个字符 参 数 : pData ----- 字符串 Length — 长度 *************************************************/ void RS485_Send_Data(uint8 *buf,uint8 len) { while(len–) { USART2->TDR = (*buf & (uint16_t)0x01FF); while((USART2->ISR & USART_FLAG_TC) == RESET); while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET); buf++; } } void USART2_Send(uint8 *buf,uint8 len) { USART2->CR1&=~(USART_CR1_RXNEIE|USART_CR1_RE); //不允许接收 //D_485_TXD; uart2_tx_p = buf; uart2_tx_len = len; uart2_rx_len = 0; while(!((USART2->ISR ) & USART_ISR_TXE)); //发送寄存器为空 USART2->TDR= *buf; //发送 USART2->CR1|=(USART_CR1_TE+USART_CR1_TCIE); //允许发送 } void USART2_IRQHandler(void) { // uint8 USART_data; //单个数据 if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) { USART_ClearITPendingBit(USART2,USART_IT_RXNE); Rx2_Frame[uart2_rx_len] = USART2->RDR;//读取接收到的数据 if(uart2_rx_len ==0) { if(Rx2_Frame[0] == prd_info.product_addr || Rx2_Frame[0] == 0xFA || Rx2_Frame[0] == 0xF1) { uart2_rx_len++; uart2_start_time(); } } else { if(Rx2_Frame[1] == 0x03 || Rx2_Frame[1] == 0x06 || Rx2_Frame[1] == 0x01) { uart2_rx_len++; uart2_start_time(); } else { uart2_rx_len =0; } } if(uart2_rx_len >=40) { uart2_rx_len=39; } } if(USART_GetITStatus(USART2, USART_IT_TC) != RESET) { if(uart2_tx_len>1) { uart2_tx_p++; uart2_tx_len–; USART2->TDR= *uart2_tx_p; //发送 } else { USART2->CR1&=~(USART_CR1_TCIE); //禁止发送 加上这个会通讯失败USART_CR1_TE+ // D_485_RXD; USART2->CR1 |= USART_CR1_RXNEIE | USART_CR1_RE | USART_CR1_UE; //使能USART2接收中断 允许接收 使能USART2 uart2_tx_len=0; } } else { USART_ClearFlag(USART2,0xFFFF); //产生错误中断后,全部清除中断 } } #if 1 #pragma import(__use_no_semihosting) //标准库需要的支持函数 struct __FILE { int handle; }; FILE __stdout; //定义_sys_exit()以避免使用半主机模式 void _sys_exit(int x) { x = x; } //重定义fputc函数 int fputc(int ch, FILE *f) { while((USART1->ISR&0X40)==0);//循环发送,直到发送完毕 USART1->TDR = (uint8) ch; return ch; } #endif void RS485_printf (char *fmt, …) { char buffer[64]; // 数据长度 uint8 i = 0; va_list arg_ptr; va_start(arg_ptr, fmt); vsnprintf(buffer,64, fmt, arg_ptr); while ((i < 64) && (i < strlen(buffer))) { RS485_SendByte(buffer[i++]); while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET); } va_end(arg_ptr); } #include “User_Cfg.h” /* 串口通讯数据结构定义 */ ComSetTypeDef ComSet; //通讯配置 ComBuffTypeDef ComBuff; //通讯数据缓冲区 /*************************************************************************************************** 函数名称: InitUSART1 函数功能: PY32 USART1设置 入口参数: 无 出口参数: 无 使用说明:初始化USARTx相关寄存器 创建日期: 2024年03月01日 修改日期: 修改原因: ***************************************************************************************************/ void InitUSART1( void ) { LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_USART1); // 使能USART1的时钟 InitUSART1_GPIO(); // 串口引脚初始化 // R_RS485(); // 485读使能 WRITE_REG(UART1->CR1,0x00000000U); // UART1寄存器初始化 WRITE_REG(UART1->CR2,0x00000000U); WRITE_REG(UART1->CR3,0x00000000U); MCAL_UART_SetBaud(__UART1_BAUD,__UART1_BIT_MOD); // 设置波特率、比特率格式,默认9600、N、8、1 SET_BIT(UART1->CR1,USART_CR1_RE); // UART1接收使能 SET_BIT(UART1->CR1,USART_CR1_TE); // UART1发送使能 SET_BIT(UART1->CR1,USART_CR1_RXNEIE); // 使能UART1接收中断 SET_BIT(UART1->CR1,USART_CR1_UE); // 使能UART1模块 NVIC_SetPriority(USART1_IRQn,IPR_USART1); // 配置串口中断优先级配置 NVIC_EnableIRQ(USART1_IRQn); // 串口中断使能 ComBuff.Flag = USART_FREE; ComBuff.TxLen = 0; ComBuff.RxLen = 0; ComBuff.TxPoint = 0; ComBuff.RxPoint = 0; ComSet.bit_mod = __UART1_BIT_MOD; ComSet.BaudRate = __UART1_BAUD; } /*************************************************************************************************** 函数名称: InitUSART1_GPIO 函数功能: PY32 USART1的引脚配置设置 入口参数: 无 出口参数: 无 使用说明:初始化串口引脚需要的相关寄存器 创建日期: 2024年03月01日 修改日期: 修改原因: **************************************************************************************************/ //void InitUSART1_GPIO( void ) //{ // / 使能GPIOB时钟 */ // LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA); // /* 创建串口需要的引脚初始化结构体 */ //// LL_GPIO_InitTypeDef GPIO3_InitStruct = {0}; // PB3: RS485_C // LL_GPIO_InitTypeDef GPIO3_InitStruct = {0}; // PA3: RS485_Tx // LL_GPIO_InitTypeDef GPIO4_InitStruct = {0}; // PA4: RS485_Rx //// GPIO3_InitStruct.Pin = LL_GPIO_PIN_3; // 选择3号引脚 //// GPIO3_InitStruct.Mode = LL_GPIO_MODE_OUTPUT; // 通用输出模式 //// GPIO3_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; // 高速 //// GPIO3_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; // 推挽输出 //// GPIO3_InitStruct.Pull = LL_GPIO_PULL_NO; // 即不上拉也不下拉 //// LL_GPIO_Init(GPIOB,&GPIO3_InitStruct); // 初始化 // GPIO3_InitStruct.Pin = LL_GPIO_PIN_3; // 选择3号引脚 // GPIO3_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; // 开启复用功能 // GPIO3_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; // 高速 // GPIO3_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; // 推挽输出 // GPIO3_InitStruct.Pull = LL_GPIO_PULL_NO; // 即不上拉也不下拉 // GPIO3_InitStruct.Alternate = LL_GPIO_AF1_USART1; // 复用为串口USART1功能 // LL_GPIO_Init(GPIOA,&GPIO3_InitStruct); // 初始化 // GPIO4_InitStruct.Pin = LL_GPIO_PIN_4; // 选择4号引脚 // GPIO4_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; // 开启复用功能 // GPIO4_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; // 高速 // GPIO4_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; // 推挽输出 // GPIO4_InitStruct.Pull = LL_GPIO_PULL_NO; // 即不上拉也不下拉 // GPIO4_InitStruct.Alternate = LL_GPIO_AF1_USART1; // 复用为串口USART1功能 // LL_GPIO_Init(GPIOA,&GPIO4_InitStruct); // 初始化 //} void InitUSART1_GPIO(void) { LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA); // 使能GPIOA时钟 LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; // 配置PA3为USART1_TX GPIO_InitStruct.Pin = LL_GPIO_PIN_3; GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; GPIO_InitStruct.Alternate = LL_GPIO_AF1_USART1; // 复用为USART1功能 LL_GPIO_Init(GPIOA, &GPIO_InitStruct); // 配置PA4为USART1_RX GPIO_InitStruct.Pin = LL_GPIO_PIN_4; GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; GPIO_InitStruct.Alternate = LL_GPIO_AF1_USART1; // 复用为USART1功能 LL_GPIO_Init(GPIOA, &GPIO_InitStruct); } /*************************************************************************************************** 函数名称:UARTx_BitModeSet() 函数功能:STM32 UART位模式设置 入口参数:UARTx :UART外设 com_bps :最大为115200BPS parity :UART_PARITY_NONE、UART_PARITY_EVEN、UART_PARITY_ODD stop :UART_STOPBITS_1、UART_STOPBITS_2 出口参数:无 使用说明:初始化UARTx相关寄存器 创建日期:2020年01月01日 ***************************************************************************************************/ void UARTx_BitModeSet(USART_TypeDef *UARTx,uint32 com_bps,uint32 parity,uint32 stop) { uint32 temp_cr1_ue; uint32 uart_freq = SystemCoreClock >> APBPrescTable[(RCC->CFGR & RCC_CFGR_PPRE) >> RCC_CFGR_PPRE_Pos]; // UART总线频率 uint32 uart_brr,div_mant,div_fraq; div_mant = uart_freq / (16 * com_bps); div_fraq = uart_freq / com_bps - div_mant * 16; uart_brr = div_mant * 16 + div_fraq; temp_cr1_ue = READ_BIT(UARTx->CR1,USART_CR1_UE); // 获取当前CR1_UE状态 CLEAR_BIT(UARTx->CR1,USART_CR1_UE); // 清零CR1_UE位 MODIFY_REG(UARTx->CR1,(USART_CR1_PS | USART_CR1_PCE),parity); // 设置奇偶校验位 MODIFY_REG(UARTx->CR2,USART_CR2_STOP,stop); // 设置停止位 WRITE_REG (UARTx->BRR,uart_brr); // 设置波特率 if(parity == UART_PARITY_EVEN || parity == UART_PARITY_ODD) // 奇偶校验,字长设为9 { MODIFY_REG(UARTx->CR1,USART_CR1_M,UART_WORDLENGTH_9B); } else // 无校验,字长设为8 { MODIFY_REG(UARTx->CR1,USART_CR1_M,UART_WORDLENGTH_8B); } UARTx->CR1 |= temp_cr1_ue; // 恢复CR1_UE状态 } /*************************************************************************************************** 函数名称:MCAL_UART_SetBaud() 函数功能:串口设置波特率 入口参数:com_bps :最大为115200BPS com_mod :比特率格式(COM_MODE_8N1、COM_MODE_8N2、COM_MODE_8O1、COM_MODE_8E1) 出口参数:无 使用说明:无 创建日期:2020年01月01日 ***************************************************************************************************/ void MCAL_UART_SetBaud(uint32 com_bps,uint08 com_mod) { if((com_bps % 600 != 0) || (com_mod >= 4)) // 参数合理性检查 { return; } USART_TypeDef *UARTx = USART1; // 只有一个串口 MCAL_UART_TimeoutCfg(com_bps); // 重新计算通信超时时间 if(com_mod == 0) // 无校验、1停止位 { UARTx_BitModeSet(UARTx,com_bps,UART_PARITY_NONE,UART_STOPBITS_1); } else if(com_mod == 1) // 无校验、2停止位 { UARTx_BitModeSet(UARTx,com_bps,UART_PARITY_NONE,UART_STOPBITS_2); } else if(com_mod == 2) // 奇校验、1停止位 { UARTx_BitModeSet(UARTx,com_bps,UART_PARITY_ODD,UART_STOPBITS_1); } else if(com_mod == 3) // 偶校验、1停止位 { UARTx_BitModeSet(UARTx,com_bps,UART_PARITY_EVEN,UART_STOPBITS_1); } } /*************************************************************************************************** 函数名称:MCAL_UART_UpdateBaud() 函数功能:串口更新波特率 入口参数:com_bps:最大为115200BPS com_mod:比特率格式(COM_MODE_8N1、COM_MODE_8N2、COM_MODE_8O1、COM_MODE_8E1) 出口参数:无 使用说明:无 创建日期:2020年01月01日 ***************************************************************************************************/ void MCAL_UART1_UpdateBaud(uint32 com_bps,uint08 com_mod) { if((com_bps != ComSet.BaudRate) || (com_mod != ComSet.BaudRate)) { ComSet.BaudRate = com_bps; ComSet.bit_mod = com_mod; #if(__UARTx_SETUP) MCAL_UART_SetBaud(com_bps,com_mod); // 设置波特率和通信格式 MCAL_UART_TimeoutCfg(com_bps); // 重新计算通信超时时间 #endif } } /*************************************************************************************************** 函数名称: USART1Rst 函数功能: PY32 USART1设置 入口参数: 无 出口参数: 无 使用说明:初始化USARTx相关寄存器 创建日期: 2024年03月01日 修改日期: 修改原因: ***************************************************************************************************/ void USART1Rst(void) { uint08 IIR; // R_RS485(); IIR = USART1->DR; IIR = IIR; USART1->SR = 0; ComBuff.Flag = USART_FREE; ComBuff.TxLen = 0; ComBuff.RxLen = 0; ComBuff.TxPoint = 0; ComBuff.RxPoint = 0; WRITE_REG(UART1->CR1,0x00000000U); // UART1寄存器初始化 WRITE_REG(UART1->CR2,0x00000000U); WRITE_REG(UART1->CR3,0x00000000U); MCAL_UART_SetBaud(ComSet.BaudRate,ComSet.bit_mod); // 重新配置 SET_BIT(UART1->CR1,USART_CR1_RE); // UART1接收使能 SET_BIT(UART1->CR1,USART_CR1_TE); // UART1发送使能 SET_BIT(UART1->CR1,USART_CR1_RXNEIE); // 使能UART1接收中断 SET_BIT(UART1->CR1,USART_CR1_UE); // 使能UART1模块 StopUSART1Timer(); } /*************************************************************************************************** 函数名称:MCAL_UART_WaitTxdIdle() 函数功能:等待UART发送完成 入口参数:无 出口参数:无 使用说明:无 创建日期:2020年01月01日 ***************************************************************************************************/ void UART1_WaitTxdIdle(void) { // for(uint32 cnt = 0;cnt < 500;cnt ++) // 等待UART发送完成 // { // if( (ComBuff.Flag != USART_RECEIVING) && (ComBuff.Flag != USART_SENDING) ) // { // break; // } // FeedIWG(); // 清除看门狗 // MCAL_DelaymS(2); // 延时2mS // } } /*************************************************************************************************** 函数名称:MCAL_UART_TimeoutCfg() 函数功能:计算串口通信超时时间 入口参数:com_bps:通信波特率 出口参数:无 使用说明:无 创建日期:2020年01月01日 *************************************************************************************************/ void MCAL_UART_TimeoutCfg(uint32 com_bps) { ComSet.ComTimer = 1000001135/com_bps; } /*************************************************************************************************** 函数名称: USART1_IRQHandler 函数功能: PY32 USART1的全局中断服务程序 入口参数: 无 出口参数: 无 使用说明:无 创建日期: 2024年03月01日 修改日期: 修改原因: ***************************************************************************************************/ void APP_Usart1IRQ_Callback(void) { volatile uint32 IIR; IIR = USART1->SR & USART1->CR1; /* 清除中断标志位 */ USART1->SR = 0; StopUSART1Timer();//停止3.5T定时器? // 读寄存器非空 if( IIR & USART_SR_RXNE ) { RstUSART1Timer(); // ComBuff.RxBuff[ ComBuff.RxPoint ] = LL_USART_ReceiveData8(USART1); ComBuff.RxPoint++; ComBuff.RxLen++; ComBuff.Flag = USART_RECEIVING; if( ComBuff.RxPoint >= USART_BUFF_LEN ) { ComBuff.RxPoint = 0; ComBuff.RxLen = 0; } } // 发送寄存器空 else if( IIR & USART_SR_TXE ) { if( ComBuff.TxPoint < ComBuff.TxLen ) { USART1->DR = ComBuff.TxBuff[ ComBuff.TxPoint ]; ComBuff.TxPoint++; ComBuff.Flag = USART_SENDING; } else { USART1->CR1 &= ~USART_CR1_TXEIE;//OFF TXE INT USART1->CR1 |= USART_CR1_TCIE ;//ON TC INT } } // 发送完成 else if( IIR & USART_SR_TC ) { USART1Rst(); ComBuff.Flag = USART_SEND_ACHIEVE; // R_RS485(); } // 其他情况 else { USART1Rst(); } } /*************************************************************************************************** 函数名称: USART1_Send 函数功能: PY32 USART1起始发送函数 入口参数: 无 出口参数: 无 使用说明:无 创建日期: 2024年03月04日 ***************************************************************************************************/ void USART1_Send( sint32 Len ) { //// W_RS485(); if( Len>USART_BUFF_LEN ) Len = USART_BUFF_LEN; USART1->CR1 &= ~USART_CR1_RE; // USART串口接收禁止 USART1->DR = ComBuff.TxBuff[0]; // 发送第一个数据 ComBuff.TxLen = Len; ComBuff.TxPoint = 1; ComBuff.Flag = USART_SENDING; USART1->CR1 |= USART_CR1_TXEIE; // 发送完成中断使能 } // /* CRC16校验 */ // const uint08 auchCRCHi[] = { }; const uint08 auchCRCLo[] = { }; /*************************************************************************************************** 函数名称:CRC16() 函数功能:计算指定长度数据的CRC校验码 入口参数:*dat:数据起始地址 len :数据长度 出口参数:CRC校验码 使用说明:无 创建日期:2020年01月01日 ***************************************************************************************************/ uint16 CRC16(const uint08 *dat,uint32 len) { uint08 uchCRCHi = 0xFF,uchCRCLo = 0xFF; uint16 cnt = 0; while(len --) { cnt = uchCRCLo ^ *dat ++; uchCRCLo = uchCRCHi ^ auchCRCHi[cnt]; uchCRCHi = auchCRCLo[cnt]; } return (uchCRCHi | ((uint16)uchCRCLo << 8)); } /*************************************************************************************************** 函数名称:CRC16_Load() 函数功能:计算指定长度数据的CRC校验码 入口参数:*dat:数据起始地址 len :数据长度 出口参数:CRC校验码 使用说明:无 创建日期:2020年01月01日 ***************************************************************************************************/ void CRC16_Load(uint08 *dat,uint32 len) { uint08 uchCRCHi = 0xFF,uchCRCLo = 0xFF; uint16 cnt = 0; while(len --) { cnt = uchCRCLo ^ *dat ++; uchCRCLo = uchCRCHi ^ auchCRCHi[cnt]; uchCRCHi = auchCRCLo[cnt]; } *dat ++ = uchCRCLo; *dat ++ = uchCRCHi; }uint8 Frame_CRC16(uint8 *data_p) { uint8 Command_temp; uint16 CRCtemp=0; uint16 CRCdata=0; if(data_p[1]==0x03||data_p[1]==0x06) //判断命令是否为本机命令;读取命令:0x03,校验命令:0x06 { CRCdata = CRC16(data_p,6); // CRC校验,将校验值赋给CRCdata CRCtemp=data_p[6]; CRCtemp <<=8; CRCtemp |= data_p[7]; if(CRCdata==CRCtemp) { Command_temp = data_p[1]; return Command_temp; //返回命令值 } } return 0; //返回命令值 } //针对0x06功能码返回 void pc_return_0x06(void) { uint16 CRC_temp = 0; Tx2_Frame[0]=Rx2_Frame[0]; Tx2_Frame[1]=Rx2_Frame[1]; Tx2_Frame[2]=Rx2_Frame[2]; Tx2_Frame[3]=Rx2_Frame[3]; Tx2_Frame[4]=Rx2_Frame[4]; Tx2_Frame[5]=Rx2_Frame[5]; CRC_temp = CRC16(Tx2_Frame,6); Tx2_Frame[6]=(uint8)(CRC_temp>>8); Tx2_Frame[7]=(uint8)(CRC_temp); USART2_Send(Tx2_Frame,8); } void Return_03(uint16 add, uint16 *p) { uint8 i,temp[2]; uint16 CRC_temp; uint16 *u16_P1,*u16_p2; Tx2_Frame[0] = (uint8_t)prd_info.product_addr; Tx2_Frame[1] = Rx2_Frame[1]; Tx2_Frame[2] = Rx2_Frame[5] <<1; u16_P1 = p; u16_P1 += add; u16_p2 = (uint16 *)temp; for(i=0; i<Rx2_Frame[5]; i++) { *u16_p2 = *u16_P1; Tx2_Frame[i*2 + 3] = temp[1]; Tx2_Frame[i*2 + 4] = temp[0]; u16_P1++; } CRC_temp = CRC16(Tx2_Frame,Rx2_Frame[5]*2+3); Tx2_Frame[Rx2_Frame[5]*2+3] = (uint8)(CRC_temp>>8); Tx2_Frame[Rx2_Frame[5]*2+4] = (uint8)(CRC_temp); USART2_Send(Tx2_Frame,Rx2_Frame[5]*2+5); } void Return_03_i(void) { uint16 i_temp,CRC_temp; i_temp = prd_info.current; Tx2_Frame[0] = (uint8_t)prd_info.product_addr; Tx2_Frame[1] = Rx2_Frame[1]; Tx2_Frame[2] = Rx2_Frame[5] <<1; Tx2_Frame[3] = (uint8)(i_temp>>8); Tx2_Frame[4] = (uint8)(i_temp); if(1 ==pc_rx_data) { CRC_temp = CRC16(Tx2_Frame,5); Tx2_Frame[5] = (uint8)(CRC_temp>>8); Tx2_Frame[6] = (uint8)(CRC_temp); USART2_Send(Tx2_Frame,7); } else if (2 == pc_rx_data) { Tx2_Frame[5] = 0; Tx2_Frame[6] = 0; CRC_temp = CRC16(Tx2_Frame,7); Tx2_Frame[7] = (uint8)(CRC_temp>>8); Tx2_Frame[8] = (uint8)(CRC_temp); USART2_Send(Tx2_Frame,9); } }有没有接收到数据又回传回去的地方

完成一个仓储环境监测的模拟系统。具体要求如下: 1. DHT11模块完成温湿度测量,5s更新,数值显示于数码管,同时打印到串口。温度超过阈值触发蜂鸣器短鸣,同时启动风扇小马达; 2. LDR模块完成环境照度测量,4s更新,数值显示于数码管,同时打印到串口。照度超过阈值启动PWM调光(高、中、低三级调光)。 3. 按键循环切换显示模式,按第1下固定显示温度,按第二下固定显示照度,按第三下恢复默认的自动显示模式。按键用外部中断实现。 #include "systick.h" static u8 fac_us=0; //us延时倍乘数 static u16 fac_ms=0; //ms延时倍乘数 //初始化延迟函数 //SYSTICK的时钟固定为AHB时钟的1/8 //SYSCLK:系统时钟频率 void systick_init(u8 SYSCLK) { SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); fac_us = SYSCLK/8; fac_ms = (u16)fac_us * 1000; } //延时nus //nus为要延时的us数. void delay_us(u32 nus) { u32 temp; SysTick->LOAD=nus*fac_us; //时间加载 SysTick->VAL=0x00; //清空计数器 SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数 do { temp=SysTick->CTRL; }while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达 SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器 SysTick->VAL =0X00; //清空计数器 } //延时nms //注意nms的范围 //SysTick->LOAD为24位寄存器,所以,最大延时为: //nms<=0xffffff*8*1000/SYSCLK //SYSCLK单位为Hz,nms单位为ms //对72M条件下,nms<=1864 void delay_ms(u16 nms) { u32 temp; SysTick->LOAD = (u32)nms*fac_ms; //时间加载(SysTick->LOAD为24bit) SysTick->VAL = 0x00; //清空计数器 SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk ; //开始倒数 do { temp=SysTick->CTRL; } while((temp&0x01) && !(temp&(1<<16))); //等待时间到达 SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; //关闭计数器 SysTick->VAL = 0x00; //清空计数器 } #include "display.h" DisplayStruct dsp; void segDisplay(void); // 共阴极数码管,阴极位选(0有效),阳极段选(1有效) const u16 segCode[11] = { /* 0 1 2 3 4 5 6 7 */ 0x003F, 0x0006, 0x005B, 0x004F, 0x0066, 0x006D, 0x007D, 0x0007, /* 8 9 off */ 0x007F, 0x006F, 0x0000 }; /******************************************************************************* * @brief 初始化数码管用到的GPIO端口和dsp结构体 * @param None * @retval None *******************************************************************************/ void display_init(void) { GPIO_InitTypeDef GPIO_InitStructure = {0}; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE); // PA0~PA7: 段选(分别连接引脚A~G); // PB12~PB15:位选(分别连接引脚D1~D4) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOB, &GPIO_InitStructure); dsp.currDigit = 1; // dsp结构体的初始化 dsp.SegDisplay = segDisplay; } /*********************************************************************************** * @brief 设置数码管要显示的4位数值。 * @param dsp:数码管结构体指针;value[4]:4位数值;dotBit:小数点位置(没有小数点则置0) * @retval None ***********************************************************************************/ void setValue(DisplayStruct *dsp, u8 value[4], u8 dotBit) { dsp->digit[0] = value[0]; dsp->digit[1] = value[1]; dsp->digit[2] = value[2]; dsp->digit[3] = value[3]; dsp->dotDigit = dotBit; } void setLightValue(DisplayStruct *dsp, u8 dotBit) { dsp->digit[0] = 1; // 参数编号 dsp->digit[1] = 10; // 第二位空缺 dsp->digit[2] = ldr.light/10; dsp->digit[3] = ldr.light%10; // dsp->dotDigit = dotBit; // 小数点位置 } void setTempValue(DisplayStruct *dsp, u8 dotBit) { dsp->digit[0] = 2; dsp->digit[1] = 10; dsp->digit[2] = dht11.temp/10; dsp->digit[3] = dht11.temp%10; dsp->dotDigit = dotBit; } void setHumiValue(DisplayStruct *dsp, u8 dotBit) { dsp->digit[0] = 3; dsp->digit[1] = 10; dsp->digit[2] = dht11.humi/10; dsp->digit[3] = dht11.humi%10; dsp->dotDigit = dotBit; } /******************************************************************************* * @简 介 段选,让某一位数码管显示指定的数字 * @输入参数 value:段码数组的序号(0~9),代表要显示的数字 * @retval * 备注:只操作PA的低8位,不要影响高8位。 ********************************************************************************/ void seg(uint8_t value) { if(value < sizeof(segCode)) // 避免数组溢出 { GPIOA->ODR &= 0xFF00; GPIOA->ODR |= segCode[value]; } } /******************************************************************************** * 简 介 位选,一次只能选一位。 * 输入参数 com:位数(取值1~4,从左到右) * 返回值 无 * 备注:只操作PB的高4位(置0),不要影响其他位。 ********************************************************************************/ void com(uint8_t currDigit) { // 数码管位选(0有效) GPIOB->ODR |= 0xF000; GPIOB->ODR &= ~(0x1000<<(currDigit-1)); } /******************************************************************************** * 简介 在数码管上逐位显示其段码(由Timer中断服务函数调用) * 参数 无 * 返回值 无 ********************************************************************************/ void segDisplay(void) { seg(10); // 消隐之前的显示内容 com(dsp.currDigit); // 位选,从COM1到COM4逐次移位,实现动态显示 if(dsp.currDigit != dsp.dotDigit) // 当前位不显示小数点 seg(dsp.digit[dsp.currDigit-1]); else // 当前位要显示小数点 { GPIO_Write(GPIOA, segCode[dsp.digit[dsp.currDigit-1]]| 0x0080); //GPIOA->ODR &= 0xFF00; //GPIOA->ODR |= (segCode[dsp.currDigit-1]|0x0080); } if(++dsp.currDigit > DSP_DIGIT) // 从当前位右移到下一位 dsp.currDigit = 1; } #include "display.h" DisplayStruct dsp; void segDisplay(void); // 共阴极数码管,阴极位选(0有效),阳极段选(1有效) const u16 segCode[11] = { /* 0 1 2 3 4 5 6 7 */ 0x003F, 0x0006, 0x005B, 0x004F, 0x0066, 0x006D, 0x007D, 0x0007, /* 8 9 off */ 0x007F, 0x006F, 0x0000 }; /******************************************************************************* * @brief 初始化数码管用到的GPIO端口和dsp结构体 * @param None * @retval None *******************************************************************************/ void display_init(void) { GPIO_InitTypeDef GPIO_InitStructure = {0}; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE); // PA0~PA7: 段选(分别连接引脚A~G); // PB12~PB15:位选(分别连接引脚D1~D4) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOB, &GPIO_InitStructure); dsp.currDigit = 1; // dsp结构体的初始化 dsp.SegDisplay = segDisplay; } /*********************************************************************************** * @brief 设置数码管要显示的4位数值。 * @param dsp:数码管结构体指针;value[4]:4位数值;dotBit:小数点位置(没有小数点则置0) * @retval None ***********************************************************************************/ void setValue(DisplayStruct *dsp, u8 value[4], u8 dotBit) { dsp->digit[0] = value[0]; dsp->digit[1] = value[1]; dsp->digit[2] = value[2]; dsp->digit[3] = value[3]; dsp->dotDigit = dotBit; } void setLightValue(DisplayStruct *dsp, u8 dotBit) { dsp->digit[0] = 1; // 参数编号 dsp->digit[1] = 10; // 第二位空缺 dsp->digit[2] = ldr.light/10; dsp->digit[3] = ldr.light%10; // dsp->dotDigit = dotBit; // 小数点位置 } void setTempValue(DisplayStruct *dsp, u8 dotBit) { dsp->digit[0] = 2; dsp->digit[1] = 10; dsp->digit[2] = dht11.temp/10; dsp->digit[3] = dht11.temp%10; dsp->dotDigit = dotBit; } void setHumiValue(DisplayStruct *dsp, u8 dotBit) { dsp->digit[0] = 3; dsp->digit[1] = 10; dsp->digit[2] = dht11.humi/10; dsp->digit[3] = dht11.humi%10; dsp->dotDigit = dotBit; } /******************************************************************************* * @简 介 段选,让某一位数码管显示指定的数字 * @输入参数 value:段码数组的序号(0~9),代表要显示的数字 * @retval * 备注:只操作PA的低8位,不要影响高8位。 ********************************************************************************/ void seg(uint8_t value) { if(value < sizeof(segCode)) // 避免数组溢出 { GPIOA->ODR &= 0xFF00; GPIOA->ODR |= segCode[value]; } } /******************************************************************************** * 简 介 位选,一次只能选一位。 * 输入参数 com:位数(取值1~4,从左到右) * 返回值 无 * 备注:只操作PB的高4位(置0),不要影响其他位。 ********************************************************************************/ void com(uint8_t currDigit) { // 数码管位选(0有效) GPIOB->ODR |= 0xF000; GPIOB->ODR &= ~(0x1000<<(currDigit-1)); } /******************************************************************************** * 简介 在数码管上逐位显示其段码(由Timer中断服务函数调用) * 参数 无 * 返回值 无 ********************************************************************************/ void segDisplay(void) { seg(10); // 消隐之前的显示内容 com(dsp.currDigit); // 位选,从COM1到COM4逐次移位,实现动态显示 if(dsp.currDigit != dsp.dotDigit) // 当前位不显示小数点 seg(dsp.digit[dsp.currDigit-1]); else // 当前位要显示小数点 { GPIO_Write(GPIOA, segCode[dsp.digit[dsp.currDigit-1]]| 0x0080); //GPIOA->ODR &= 0xFF00; //GPIOA->ODR |= (segCode[dsp.currDigit-1]|0x0080); } if(++dsp.currDigit > DSP_DIGIT) // 从当前位右移到下一位 dsp.currDigit = 1; } #include "usart.h" int fputc(int ch,FILE *p) //函数默认的,在使用printf函数时自动调用 { USART_SendData(USART1,(u8)ch); while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET); return ch; } //串口1中断服务程序 //注意,读取USARTx->SR能避免莫名其妙的错误 u8 USART1_RX_BUF[USART1_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节. //接收状态 //bit15, 接收完成标志 //bit14, 接收到0x0d //bit13~0, 接收到的有效字节数目 u16 USART1_RX_STA=0; //接收状态标记 /******************************************************************************* * 函 数 名 : USART1_Init * 函数功能 : USART1初始化函数 * 输 入 : bound:波特率 * 输 出 : 无 *******************************************************************************/ void usart1_init(u32 baud) { //GPIO端口设置 GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); /* 配置GPIO的模式和IO口 */ GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9; //串口输出TX:PA9 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(GPIOA,&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10; //串口输入RX:PA10 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING; //模拟输入 GPIO_Init(GPIOA,&GPIO_InitStructure); //USART1 初始化设置 USART_InitStructure.USART_BaudRate = baud; //波特率设置 USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式 USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位 USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式 USART_Init(USART1, &USART_InitStructure); //初始化串口1 USART_Cmd(USART1, ENABLE); //使能串口1 USART_ClearFlag(USART1, USART_FLAG_TC); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启相关中断 //Usart1 NVIC 配置 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口1中断通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3 NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器、 } /******************************************************************************* * 函 数 名 : USART1_IRQHandler * 函数功能 : USART1中断函数 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void USART1_IRQHandler(void) //串口1中断服务程序 { u8 r; if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断 { r =USART_ReceiveData(USART1);//(USART1->DR); //读取接收到的数据 if((USART1_RX_STA&0x8000)==0)//接收未完成 { if(USART1_RX_STA&0x4000)//接收到了0x0d { if(r!=0x0a)USART1_RX_STA=0;//接收错误,重新开始 else USART1_RX_STA|=0x8000; //接收完成了 } else //还没收到0X0D { if(r==0x0d)USART1_RX_STA|=0x4000; else { USART1_RX_BUF[USART1_RX_STA&0X3FFF]=r; USART1_RX_STA++; if(USART1_RX_STA>(USART1_REC_LEN-1))USART1_RX_STA=0;//接收数据错误,重新开始接收 } } } } } #include "dht11.h" #include "beep.h" Dht11Struct dht11 = {0}; void SET_DHT11_IO_OUT(void); void SET_DHT11_IO_IN(void); void DHT11_RequestData(void); u8 DHT11_RespondRequest(void); u8 DHT11_Read_Data(u8 *temp, u8 *humi); void DHT11_OnTempChange(u8 temp_threshold); // DHT11_PIN初始化 // 返回值: 无 extern void dht11_init() { GPIO_InitTypeDef GPIO_InitStructure; // 数据引脚初始化 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 数据引脚 GPIO_InitStructure.GPIO_Pin = DHT11_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(DHT11_PORT, &GPIO_InitStructure); GPIO_SetBits(DHT11_PORT, DHT11_PIN); // 初始输出状态:高电平 // 结构体初始化 dht11.period = DHT11_PERIOD; dht11.temp_threshold = TEMP_THRESHOLD; dht11.getData = DHT11_Read_Data; // 获取温湿度数据的函数 dht11.onTempChange = DHT11_OnTempChange; // 温度超过阈值的处理函数 // 做一次数据请求测试,检查设备状态 DHT11_RequestData(); if (DHT11_RespondRequest() == SUCCESS) { dht11.state = STANDBY; printf("DHT11 Init OK!\r\n"); } else { dht11.state = FAIL; printf("DHT11 Check Error!\r\n"); } } // 复位DHT11,单片机向DHT11发起数据采集请求 // 时序图的黑线部分 static void DHT11_RequestData() { SET_DHT11_IO_OUT(); // 数据引脚配置为输出模式 DHT11_DQ_OUT = 0; delay_ms(20); // 低电平持续至少18ms DHT11_DQ_OUT = 1; delay_us(30); // 高电平持续20~40us } // DHT11响应单片机的数据请求 // 返回值:SUCCESS or FAILURE static u8 DHT11_RespondRequest() { u8 retry=0; SET_DHT11_IO_IN(); // 数据引脚设为输入模式,接收DHT11的响应 while (DHT11_DQ_IN && retry<100) // 等待输入由高变低 { retry++; if(retry >= 100) return FAILURE; // 等待时间过长,返回异常。 delay_us(1); } retry=0; while (!DHT11_DQ_IN && retry<100) // 低电平持续时间80us { retry++; if(retry >= 100) return FAILURE; // 低电平持续时间过长,返回异常。 delay_us(1); } return SUCCESS; } //DHT11输出模式配置 static void SET_DHT11_IO_OUT() { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = DHT11_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出模式 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(DHT11_PORT,&GPIO_InitStructure); } //DHT11输入模式配置 static void SET_DHT11_IO_IN() { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = DHT11_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入模式,最小系统板和DHT11之间并未接上拉电阻 GPIO_Init(DHT11_PORT,&GPIO_InitStructure); } //从DHT11读取一位 //返回值:bit 1或0 //注:此函数处并未做高低电平持续时间异常的处理,因DHT11自身有校验和,即便读错1位也不会造成最终数据的错误。 // 严格来讲,除了正常情况下返回“1”或“0”,还应增加异常情况的返回值(比如“2”)。 static u8 DHT11_Read_Bit(void) { u8 retry=0; while(DHT11_DQ_IN && retry<100) // 等待输入电平由高变低(低电平持续50us) { retry++; delay_us(1); } retry=0; while(!DHT11_DQ_IN && retry<100) // 等待输入电平由低变高 { retry++; delay_us(1); } delay_us(40); // 等待40us(高电平持续26~28us表示0,持续70us表示1) if(DHT11_DQ_IN) return 1; // 40us后如果输入仍为高电平,则表示读入1;否则表示读入0。 else return 0; } //从DHT11读取一个字节 //返回值:读到的8位数据 static u8 DHT11_Read_Byte(void) { u8 i,byte; byte = 0; for (i=0;i<8;i++) { byte <<= 1; // 先前读取的数据(不足8位)全部左移一位 byte |= DHT11_Read_Bit(); // 最低位填入新读取的1位 } return byte; } //从DHT11读取一次完整的数据 //temp:温度值(整数,范围:0~50°) //humi:湿度值(整数,范围:20%~90%) //返回值:0,正常; 1,失败 static u8 DHT11_Read_Data(u8 *temp, u8 *humi) { u8 buf[5]; u8 i; DHT11_RequestData(); if(DHT11_RespondRequest() == SUCCESS) { for(i=0;i<5;i++) // 读取5组共40位数据 { buf[i] = DHT11_Read_Byte(); } if((buf[0]+buf[1]+buf[2]+buf[3]) == buf[4]) // 数据校验 { *humi = buf[0]; // 湿度整数部分 *temp = buf[2]; // 温度整数部分 return SUCCESS; } } return FAILURE; } // 采集DHT11数据并打印至串口 void dht11DataCollect() { u8 temp; u8 humi; if (DHT11_Read_Data(&temp, &humi) == SUCCESS) printf("temperature:%d℃ humidity(RH):%d \r\n", temp, humi); // 输出到串口(重定向) else printf("DHT11 data error! \r\n"); } // 温度阈值处理 void DHT11_OnTempChange(u8 temp_threshold) { if (dht11.temp > temp_threshold) { // 启动风扇(低电平触发) } else { // 关闭风扇 } } #include "ldr.h" LdrStruct ldr; static u8 getLightIntensity(void); static void OnLightChange(u8 hiLight, u8 loLight); /******************************************************************************* * 函 数 名 : adc_init * 函数功能 : ADC外设的初始化 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ static void adc_init(void) { GPIO_InitTypeDef GPIO_InitStructure; ADC_InitTypeDef ADC_InitStructure; // 1.打开相关外设的总线时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1,ENABLE); // 2.信号引脚的参数配置 GPIO_InitStructure.GPIO_Pin=LDR_PIN; // 信号引脚:PB0 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN; // 设置模拟输入模式 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_2MHz; // 设置传输速率 GPIO_Init(LDR_PORT,&GPIO_InitStructure); // 3. 输入时钟降频(<14MHz) RCC_ADCCLKConfig(RCC_PCLK2_Div6); // 分频因子6,输入时钟为72M/6=12MHz // 4. 初始化ADC参数 ADC_InitStructure.ADC_Mode=ADC_Mode_Independent; //独立模式 ADC_InitStructure.ADC_ScanConvMode=DISABLE; //单次扫描 ADC_InitStructure.ADC_ContinuousConvMode=DISABLE; //单次转换 ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None; //软件触发 ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right; //数据右对齐 ADC_InitStructure.ADC_NbrOfChannel=1; //只有1个通道 ADC_Init(ADC1,&ADC_InitStructure); // 5. 使能ADC ADC_Cmd(ADC1,ENABLE); // 6. ADC校准 ADC_ResetCalibration(ADC1); //复位校准 while(ADC_GetResetCalibrationStatus(ADC1)); ADC_StartCalibration(ADC1); //开启并完成校准 while(ADC_GetCalibrationStatus(ADC1)); } // LDR的设备初始化 extern void ldr_init() { adc_init(); ldr.period = LDR_PERIOD; ldr.high_threshold = HI_THRESHOLD; ldr.low_threshold = LO_THRESHOLD; ldr.getData = getLightIntensity; ldr.onLightChange = OnLightChange; ldr.state = STANDBY; } /******************************************************************************* * 函 数 名 : GET_ADC_Value * 函数功能 : 获取通道ch的转换值,测量times次,取平均值 * 输 入 : ch:通道编号,Rank:规则序列中的第几个转换,取值1~16; times:测量次数 * 输 出 : 通道ch的times次转换结果的平均值 *******************************************************************************/ static u16 Get_ADC_Value(u8 ch, u8 times) //获取ADC1通道ch的转换值 { u8 i; u32 Temp_val=0; ADC_RegularChannelConfig(ADC1,ch,1,ADC_SampleTime_239Cycles5); for(i=0;i<times;i++) { ADC_SoftwareStartConvCmd(ADC1,ENABLE); // 开始转换 while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)); // 等待至单次转换结束 Temp_val += ADC_GetConversionValue(ADC1); delay_ms(10); } return Temp_val/times; } /******************************************************************************* * 函 数 名 : getLightIntensity * 函数功能 : 将ADC转换值解读为光照强度 * 输 入 : 无 * 输 出 : 光照照度值(0~100, 0:照度最低;100:照度最高) *******************************************************************************/ static u8 getLightIntensity(void) //通过ADC1 通道0的值获取亮度值 { u16 value = 0; u8 lightvalue = 0; value = Get_ADC_Value(ADC_Channel_8,20); lightvalue = 100 - (u16)(value/40.95); return lightvalue; } // 添加PWM控制LED功能 static void set_led_brightness(u8 level) { switch(level) { case 0: // 低档 TIM_SetCompare2(TIM3, 125); // 25%占空比 break; case 1: // 中档 TIM_SetCompare2(TIM3, 250); // 50%占空比 break; case 2: // 高档 TIM_SetCompare2(TIM3, 375); // 75%占空比 break; } } /******************************************************************************* * 函 数 名 : OnLightChange * 函数功能 : 照度超过阈值(高阈值和低阈值)的处理措施 * 输 入 : hiLight-高阈值; loLight-低阈值 * 输 出 : 无 *******************************************************************************/ static void OnLightChange(u8 hiLight, u8 loLight) { if (ldr.light > hiLight) { set_led_brightness(0);// 照度过高,降低亮度 } else if (ldr.light < loLight) { set_led_brightness(2); // 照度过低,提升亮度 } else // 正常范围 { set_led_brightness(1); // 中等亮度 } } #include "key.h" #include "pwm.h" /******************************************************************************* * 函 数 名 : TIM3_CH2_PWM_Init * 函数功能 : TIM3通道2 PWM初始化函数 * 输 入 : per:重装载值 * psc:分频系数 * 输 出 : 无 *******************************************************************************/ void TIM3_CH2_PWM_Init(u16 per,u16 psc) { TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_OCInitTypeDef TIM_OCInitStructure; GPIO_InitTypeDef GPIO_InitStructure; /* 开启时钟 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE); // PB5引脚启用复用模式 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); // 选择TIM3部分重映射 GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3,ENABLE); /* PB5作为PWM的输出引脚 */ GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(GPIOB,&GPIO_InitStructure); // 初始化TIM3 TIM_TimeBaseInitStructure.TIM_Period=per; //自动装载值 TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //分频系数 TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //设置向上计数模式 TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure); // 设置TIM3_CH2的PWM模式,使能CH2输出,呈现出PPT展示的PWM波形 // PWM1即mode1,先输出有效电平,再输出无效电平;PWM2即mode2则正好相反。 TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; // 设置有效电平为低电平(此案例中低电平点亮D2) TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low; TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable; TIM_OC2Init(TIM3,&TIM_OCInitStructure); //输出比较通道2初始化 TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable); //使能TIM3在 CCR2 上的预装载寄存器 TIM_Cmd(TIM3,ENABLE); //使能定时器 } 数码管是4位共阴极,段选连PA0~7,位选PB12~15,STM32F103C8T6,用标准库

void zb_ReceiveDataIndication(uint16 source, uint16 command, uint16 len, uint8 *pData) { gtwData.parent = BUILD_UINT16(pData[SENSOR_PARENT_OFFSET+1], pData[SENSOR_PARENT_OFFSET]); gtwData.source = source; gtwData.temp = *pData; gtwData.humidity = *(pData+1); // Flash LED 1 once to indicate data reception HalLedSet(HAL_LED_1, HAL_LED_MODE_OFF); HalLedSet(HAL_LED_1, HAL_LED_MODE_BLINK); // 格式化显示数据 char displayBuf[50]; sprintf(displayBuf, "22145131 22145137:%d,%d\r\n", gtwData.temp, gtwData.humidity); HalUARTWrite(HAL_UART_PORT_0,(uint8 *)displayBuf, strlen(displayBuf)); // 如果是连续采集模式,计数 if (continuousReporting) { reportCount++; if (reportCount >= 10) { continuousReporting = 0; reportCount = 0; HalUARTWrite(HAL_UART_PORT_0, "22145131 22145137:采集结束\r\n", sizeof("22145131 22145137:采集结束\r\n")); } } sendGtwReport(>wData); } /****************************************************************************** * @fn uartRxCB * * @brief Callback function for UART * * @param port - UART port * event - UART event that caused callback * * @return none */ void uartRxCB(uint8 port, uint8 event) { uint8 pBuf[RX_BUF_LEN]; uint16 len; uint16 cmd; if (event != HAL_UART_TX_EMPTY) { len = HalUARTRead(HAL_UART_PORT_0, pBuf, RX_BUF_LEN); if (len > 0) { // 检查是否是PING请求 cmd = BUILD_UINT16(pBuf[SYS_PING_CMD_OFFSET+1], pBuf[SYS_PING_CMD_OFFSET]); if ((pBuf[FRAME_SOF_OFFSET] == CPT_SOP) && (cmd == SYS_PING_REQUEST)) { sysPingReqRcvd(); return; } // 处理字符串命令 if (strncmp((char *)pBuf, "0x131 ON", 8) == 0) { // LED ON命令 HalLedSet(HAL_LED_2, HAL_LED_MODE_BLINK); uint8 cmd[] = "0x131 ON"; zb_SendDataRequest(0xFFFE, SENSOR_REPORT_CMD_ID, sizeof(cmd)-1, cmd, 0, AF_ACK_REQUEST, 0); HalUARTWrite(HAL_UART_PORT_0, "22145131 22145137:LED ON ok\r\n", sizeof("22145131 22145137:LED ON ok\r\n")); } else if (strncmp((char *)pBuf, "0x131 OFF", 9) == 0) { // LED OFF命令 HalLedSet(HAL_LED_2, HAL_LED_MODE_OFF); uint8 cmd[] = "0x131 OFF"; zb_SendDataRequest(0xFFFE, SENSOR_REPORT_CMD_ID, sizeof(cmd)-1, cmd, 0, AF_ACK_REQUEST, 0); HalUARTWrite(HAL_UART_PORT_0, "22145131 22145137:LED OFF命令已发送\r\n", sizeof("22145131 22145137:LED OFF命令已发送\r\n")); } else if (strncmp((char *)pBuf, "0x132", 5) == 0) { // 单次采集命令 uint8 cmd[] = "SINGLE_REPORT"; zb_SendDataRequest(0xFFFE, SENSOR_REPORT_CMD_ID, sizeof(cmd)-1, cmd, 0, AF_ACK_REQUEST, 0); HalUARTWrite(HAL_UART_PORT_0, "22145131 22145137:one collect ok\r\n", sizeof("22145131 22145137:one collect ok\r\n")); } else if (strncmp((char *)pBuf, "0x133", 5) == 0) { // 连续采集命令 continuousReporting = 1; reportCount = 0; uint8 cmd[] = "CONTINUOUS_REPORT"; zb_SendDataRequest(0xFFFE, SENSOR_REPORT_CMD_ID, sizeof(cmd)-1, cmd, 0, AF_ACK_REQUEST, 0); HalUARTWrite(HAL_UART_PORT_0, "22145131 22145137:many collect ok\r\n", sizeof("22145131 22145137:many collect ok\r\n")); } else if (strncmp((char *)pBuf, "0x134", 5) == 0) { // 停止采集命令 continuousReporting = 0; uint8 cmd[] = "STOP_REPORT"; zb_SendDataRequest(0xFFFE, SENSOR_REPORT_CMD_ID, sizeof(cmd)-1, cmd, 0, AF_ACK_REQUEST, 0); HalUARTWrite(HAL_UART_PORT_0, "22145131 22145137:stop collect ok\r\n", sizeof("22145131 22145137:stop collect ok\r\n")); } } } } /****************************************************************************** * @fn sysPingReqRcvd * * @brief Ping request received * * @param none * * @return none */ static void sysPingReqRcvd(void) { sysPingRsp(); } /****************************************************************************** * @fn sysPingRsp * * @brief Build and send Ping response * * @param none * * @return none */ static void sysPingRsp(void) { uint8 pBuf[SYS_PING_RSP_LENGTH]; // Start of Frame Delimiter pBuf[FRAME_SOF_OFFSET] = CPT_SOP; // Length pBuf[FRAME_LENGTH_OFFSET] = 2; // Command type pBuf[FRAME_CMD0_OFFSET] = LO_UINT16(SYS_PING_RESPONSE); pBuf[FRAME_CMD1_OFFSET] = HI_UINT16(SYS_PING_RESPONSE); // Stack profile pBuf[FRAME_DATA_OFFSET] = LO_UINT16(STACK_PROFILE); pBuf[FRAME_DATA_OFFSET+ 1] = HI_UINT16(STACK_PROFILE); // Frame Check Sequence pBuf[SYS_PING_RSP_LENGTH - 1] = calcFCS(&pBuf[FRAME_LENGTH_OFFSET], (SYS_PING_RSP_LENGTH - 2)); // Write frame to UART HalUARTWrite(HAL_UART_PORT_0,pBuf, SYS_PING_RSP_LENGTH); } /****************************************************************************** * @fn sendGtwReport * * @brief Build and send gateway report * * @param none * * @return none */ static void sendGtwReport(gtwData_t *gtwData) { uint8 pFrame[ZB_RECV_LENGTH]; // Start of Frame Delimiter pFrame[FRAME_SOF_OFFSET] = CPT_SOP; // Start of Frame Delimiter // Length pFrame[FRAME_LENGTH_OFFSET] = 10; // Command type pFrame[FRAME_CMD0_OFFSET] = LO_UINT16(ZB_RECEIVE_DATA_INDICATION); pFrame[FRAME_CMD1_OFFSET] = HI_UINT16(ZB_RECEIVE_DATA_INDICATION); // Source address pFrame[FRAME_DATA_OFFSET+ ZB_RECV_SRC_OFFSET] = LO_UINT16(gtwData->source); pFrame[FRAME_DATA_OFFSET+ ZB_RECV_SRC_OFFSET+ 1] = HI_UINT16(gtwData->source); // Command ID pFrame[FRAME_DATA_OFFSET+ ZB_RECV_CMD_OFFSET] = LO_UINT16(SENSOR_REPORT_CMD_ID); pFrame[FRAME_DATA_OFFSET+ ZB_RECV_CMD_OFFSET+ 1] = HI_UINT16(SENSOR_REPORT_CMD_ID); // Length pFrame[FRAME_DATA_OFFSET+ ZB_RECV_LEN_OFFSET] = LO_UINT16(4); pFrame[FRAME_DATA_OFFSET+ ZB_RECV_LEN_OFFSET+ 1] = HI_UINT16(4); // Data pFrame[FRAME_DATA_OFFSET+ ZB_RECV_DATA_OFFSET] = gtwData->temp; pFrame[FRAME_DATA_OFFSET+ ZB_RECV_DATA_OFFSET+ 1] = gtwData->humidity; pFrame[FRAME_DATA_OFFSET+ ZB_RECV_DATA_OFFSET+ 2] = LO_UINT16(gtwData->parent); pFrame[FRAME_DATA_OFFSET+ ZB_RECV_DATA_OFFSET+ 3] = HI_UINT16(gtwData->parent); // Frame Check Sequence pFrame[ZB_RECV_LENGTH - 1] = calcFCS(&pFrame[FRAME_LENGTH_OFFSET], (ZB_RECV_LENGTH - 2) ); // Write report to UART HalUARTWrite(HAL_UART_PORT_0,pFrame, ZB_RECV_LENGTH); } /****************************************************************************** * @fn calcFCS * * @brief This function calculates the FCS checksum for the serial message * * @param pBuf - Pointer to the end of a buffer to calculate the FCS. * len - Length of the pBuf. * * @return The calculated FCS. ****************************************************************************** */ static uint8 calcFCS(uint8 *pBuf, uint8 len) { uint8 rtrn = 0; while (len--) { rtrn ^= *pBuf++; } return rtrn; } void initUart(halUARTCBack_t pf) { halUARTCfg_t uartConfig; uartConfig.configured = TRUE; uartConfig.baudRate = HAL_UART_BR_38400; uartConfig.flowControl = FALSE; uartConfig.flowControlThreshold = 48; uartConfig.rx.maxBufSize = RX_BUF_LEN; uartConfig.tx.maxBufSize = 128; uartConfig.idleTimeout = 6; uartConfig.intEnable = TRUE; uartConfig.callBackFunc = pf; HalUARTOpen (HAL_UART_PORT_0, &uartConfig); } 修改此段代码

/*************************************************************************** * @file bsp_serial1.c * Created on: 2025-03-18 * Author: YL Monitor Software group ****************************************************************************/ #include "main.h" /************************ Private macros *************************/ #if SERIAL1_DMATx_ENABLE //开启串行通信1 DMA 发送中断 -- 1 /* 串行通信 DMA发送缓冲区大小 */ #define SERIAL_TX_BUFF_SIZE 400 #endif #if SERIAL1_DMARx_ENABLE //开启串行通信1 DMA 接收中断 /* 串行通信 DMA接收缓冲区大小 */ #define SERIAL_RX_BUFF_SIZE 400 #endif /************************ Private variables *************************/ #if SERIAL1_DMATx_ENABLE //开启串行通信1 DMA 发送中断 -- 1 /* 串行通信 DMA发送缓存 */ static uint8_t DMA_TxBuff[SERIAL_TX_BUFF_SIZE]; #endif #if SERIAL1_DMARx_ENABLE //开启串行通信1 DMA 接收中断 /* 串行通信 DMA接收缓存 */ static uint8_t DMA_RxBuff[SERIAL_RX_BUFF_SIZE]; #endif /* 串行通信 接收数据队列 */ static QueueHandle_t queueRecvData = NULL; static SemaphoreHandle_t mutexSerialSend = NULL; /* 串行通信2 数据接收离线状态时间计数器 * 在硬件定时器中进行累加 * DMA接收中断中清零 * 当离线超过5ms,接收结束,或者设备离线,可以进行数据转发至上位机*/ static uint16_t recv_offline_timer_count = 0; /**************************************** * @funName : BSP_HwInitSerial1 * @Description : 串行通信口1 硬件资源初始化 * @Athor : YL Software Group * @Version : V0.0.0 * @Data : 2025/3/22 ********************************************/ void BSP_HwInitSerial1(void) { GPIO_InitTypeDef GPIO_InitStructure ={0}; USART_InitTypeDef USART_InitStructure ={0}; NVIC_InitTypeDef NVIC_InitStructure ={0}; DMA_InitTypeDef DMA_InitStructure ={0}; /****************Tx****************/ GPIO_InitStructure.GPIO_Pin = SERIAL1_TX_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//----------- GPIO_Init(SERIAL1_TX_PORT, &GPIO_InitStructure); /****************Rx****************/ GPIO_InitStructure.GPIO_Pin = SERIAL1_RX_PIN; //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入--------- GPIO_Init(SERIAL1_RX_PORT, &GPIO_InitStructure); /* 串行通信初始化 */ USART_DeInit(SERIAL1); USART_InitStructure.USART_BaudRate = SERIAL1_BAUD_RATE; //波特率 USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(SERIAL1, &USART_InitStructure); #if SERIAL1_IT_ENABLE //开启串行通信1中断 NVIC_InitStructure.NVIC_IRQChannel = SERIAL1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = SERIAL1_PreemptionPriority; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); #endif #if SERIAL1_DMATx_ENABLE //开启串行通信1 DMA 发送中断 /* DMA发送初始化 */ DMA_DeInit(SERIAL1_DMATx_Channel); DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&SERIAL1->DR); DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)DMA_TxBuff;//(uint32_t)(USART3.pbRx) 目标BUF 既是要写在哪个数组中 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize = SERIAL_TX_BUFF_SIZE;//DMA缓存的大小 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址寄存器不递增 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//内存地址递增 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//内存字节为单位 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//内存字节为单位 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //DMA_Mode_Circular DMA_Mode_Normal-工作在正常缓存模式 DMA_InitStructure.DMA_Priority = DMA_Priority_High;//4优先级之一的(高优先级) DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//非内存到内存 DMA_Init(SERIAL1_DMATx_Channel, &DMA_InitStructure); /* DMA发送中断优先级设置 */ NVIC_InitStructure.NVIC_IRQChannel = SERIAL1_DMATx_IRQn ; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = SERIAL1_DMATx_PreemptionPriority; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); DMA_ITConfig(SERIAL1_DMATx_Channel, DMA_IT_TC, ENABLE);//使能DMA1传输完成中 DMA_Cmd(SERIAL1_DMATx_Channel, ENABLE);//启用DMA1通道 #endif #if SERIAL1_DMARx_ENABLE //开启串行通信1 DMA 接收中断 /* DMA接收初始化 */ DMA_DeInit(SERIAL1_DMARx_Channel); DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&SERIAL1->DR);//源头是BUF既是(&(SERIAL1->DR)) DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)DMA_RxBuff; //(uint32_t)(USART3.pbRx) 目标BUF 既是要写在哪个数组中 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//外设做源头-外设是作为数据传输的目的地还是来源 DMA_InitStructure.DMA_BufferSize = SERIAL_RX_BUFF_SIZE;//DMA缓存的大小! 单位在下边设定 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址寄存器不递增 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//内存地址递增 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设字节为单位 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//内存字节为单位 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //循环模式DMA_Mode_Circular DMA_Mode_Normal-工作在正常缓存模式 DMA_InitStructure.DMA_Priority = DMA_Priority_High;//DMA_Priority_VeryHigh,DMA_Priority_High,DMA_Priority_Medium(初始使用); ---------------- DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//非内存到内存 DMA_Init(SERIAL1_DMARx_Channel, &DMA_InitStructure); /* DMA接收中断优先级设置 */ NVIC_InitStructure.NVIC_IRQChannel = SERIAL1_DMARx_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = SERIAL1_DMARx_PreemptionPriority; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); //DMA_ITConfig(SERIAL1_DMARx_Channel, DMA_IT_TC, ENABLE);//开启DMA1接收输完成中-需要屏蔽 DMA_ITConfig(SERIAL1_DMARx_Channel, DMA_IT_TC, DISABLE);//禁用DMA1传输完成中 DMA_Cmd(SERIAL1_DMARx_Channel, ENABLE); #endif USART_DMACmd(SERIAL1, USART_DMAReq_Rx | USART_DMAReq_Tx, ENABLE);//使能USART3的DMA发送,接收请求 //USART_ITConfig(SERIAL1, USART_IT_RXNE, ENABLE); USART_ITConfig(SERIAL1, USART_IT_IDLE, ENABLE); //启用的USART3中断 USART_Cmd(SERIAL1, ENABLE); } /********************************************* * @funName : BSP_SwInitSerial1 * @Description : 串行通信口1 软件资源初始化 * @Athor : YL Software Group * @Version : V0.0.0 * @Data : 2025/3/22 ************************************************/ void BSP_SwInitSerial1(void) { if(NULL == queueRecvData) { queueRecvData = xQueueCreate(SERIAL_DATA_QUEUE_SIZE, sizeof(uint8_t)); /* 数据接收队列创建失败 */ if(NULL == queueRecvData) { } } if(NULL == mutexSerialSend) { mutexSerialSend = xSemaphoreCreateBinary(); /* 数据发送互斥量创建失败 */ if(NULL == mutexSerialSend) { } else { /* 释放数据发送互斥量 */ xSemaphoreGive(mutexSerialSend); } } } /****************************************** * @funName : SERIAL1_IRQHandler * @Description : 串行通信口1 中断,用于处理空闲接收中断, * 获取DMA接收的数据,并缓存至数据队列 * @Athor : YL Software Group * @Version : V0.0.0 * @Data : 2025/3/22 **************************************************/ void SERIAL1_IRQHandler(void) { uint8_t byte = 0; uint16_t i = 0, rlen = 0; //if(USART_GetITStatus(SERIAL1, USART_IT_RXNE) != RESET)//接收数据寄存器不空中断 if(USART_GetITStatus(SERIAL1, USART_IT_IDLE) != RESET)//检查UART4中断是否发生 空闲线路检测中断 { portBASE_TYPE xRecvWoken = pdFALSE; byte = USART_ReceiveData(SERIAL1);//返回USART3外设最近接收到的数据 if(recv_offline_timer_count > 45) { xQueueReset(queueRecvData); } recv_offline_timer_count = 0; #if SERIAL1_DMARx_ENABLE//接收中断 rlen = SERIAL_RX_BUFF_SIZE - DMA_GetCurrDataCounter(SERIAL1_DMARx_Channel); DMA_ClearFlag(SERIAL1_DMARx_FLAG);//清除DMA2通道的挂起标志 DMA_Cmd(SERIAL1_DMARx_Channel, DISABLE);//禁止DMA1接收 if(recv_offline_timer_count > 45) { xQueueReset(queueRecvData); } recv_offline_timer_count = 0; if(rlen > 0 && NULL != queueRecvData) { /* DMA接收数据存入数据队列 */ for(i = 0; i < rlen;i ++)//i++不能写错 { //recv_offline_timer_count = 0; if(errQUEUE_FULL == xQueueSendFromISR(queueRecvData, &DMA_RxBuff[i], &xRecvWoken))//队列从ISR发送 { break; } } } USART_ClearITPendingBit(SERIAL1, USART_IT_IDLE); DMA_SetCurrDataCounter(SERIAL1_DMARx_Channel, SERIAL_RX_BUFF_SIZE);//设置当前DMA2通道3传输中的数据单元数 DMA_Cmd(SERIAL1_DMARx_Channel, ENABLE); #else USART_ClearITPendingBit(SERIAL1, USART_IT_RXNE);//清除USART3的中断挂起位 xQueueSendFromISR(queueRecvData, &byte, &xRecvWoken);//调用xQueueGenericSendFromISR()的宏 #endif } /* 全部数据发送完成,产生该标记 */ if (USART_GetITStatus(SERIAL1, USART_IT_TC) != RESET)//检查USART3中断是否发生 { USART_ClearITPendingBit(SERIAL1, USART_IT_TC); //清除USART3的中断挂起位-传输完全中断 } } #if SERIAL1_DMATx_ENABLE /***************************************** * @funName : SERIAL1_DMATx_IRQHandler * @Description : 串行通信口1 DMA 发送中断 * @Athor : YL Software Group * @Version : V0.0.0 * @Data : 2025/3/24 *******************************************/ void SERIAL1_DMATx_IRQHandler(void) { portBASE_TYPE xSendWoken = pdFALSE; if(RESET != DMA_GetITStatus(SERIAL1_DMATx_IT_TC)) { /* 关闭 DMA */ DMA_Cmd(SERIAL1_DMATx_Channel, DISABLE); /* 清除标记 */ DMA_ClearITPendingBit(SERIAL1_DMATx_IT_TC); /* 清除数据长度 */ DMA_SetCurrDataCounter(SERIAL1_DMATx_Channel, 0); USART_ITConfig(SERIAL1, USART_IT_TC, DISABLE); if(NULL != mutexSerialSend) { /* 释放 OS 数据发送权限 */ xSemaphoreGiveFromISR(mutexSerialSend, &xSendWoken); portYIELD_FROM_ISR(xSendWoken); } } } #endif /********************************************** * @funName : BSP_Send2Serial1 * @Description : 串行通信口1 DMA发送启动 * @Athor : YL Software Group * @Version : V0.0.0 * @Data : 2025/3/22 **********************************************/ void BSP_Send2Serial1(uint8_t* sbuf, const uint16_t slen) { uint16_t len = slen; if(slen == 0||NULL == sbuf) { return; } if(len > SERIAL_TX_BUFF_SIZE) { len = SERIAL_TX_BUFF_SIZE; } /******************************************** *获取OS 数据发送权限 * <DMA发送完成后,在串行通信中断服务中释放> *********************************************/ if(NULL != mutexSerialSend) { xSemaphoreTake(mutexSerialSend, portMAX_DELAY); } #if SERIAL1_DMATx_ENABLE else { while(!DMA_GetFlagStatus(SERIAL1_DMATx_IT_TC)); } #endif #if SERIAL1_DMATx_ENABLE DMA_SetCurrDataCounter(SERIAL1_DMATx_Channel, len); /*发送DMA流的地址不自增*/ SERIAL1_DMATx_Channel->CCR |= (1 << 10); /*设置接收和发送的内存地址*/ SERIAL1_DMATx_Channel->CMAR = (uint32_t)sbuf; DMA_Cmd(SERIAL1_DMATx_Channel, ENABLE); USART_DMACmd(SERIAL1, USART_DMAReq_Tx, ENABLE); #else { uint16_t i = 0; while(i < len) { USART_SendData(SERIAL1, sbuf[i]); } if(NULL != mutexSerialSend) { xSemaphoreGive(mutexSerialSend); } } #endif } /******************************************** * @funName : BSP_Recv4Serial1 * @Description : 从串口1接收数据队列获取数据 * @Athor : YL Software Group * @Version : V0.0.0 * @Data : 2025/3/22 **********************************************/ void BSP_Recv4Serial1(uint8_t * rbuf, uint16_t* rlen) { int iCnt = 0, len; *rlen = 0; if(NULL == queueRecvData || NULL == rbuf) { return; } len = uxQueueMessagesWaiting(queueRecvData);//排队等待消息 for(iCnt = 0; iCnt < len; ++iCnt) { if(pdFALSE == xQueueReceive(queueRecvData, &rbuf[iCnt], 0)) { break; } } *rlen = iCnt; } /********************************************* * @funName : BSP_GetCurRecv4Serial1 * @Description : 获取串口1接收数据队列当前数据长度 * @Athor : YL Software Group * @Version : V0.0.0 * @Data : 2025/4/03 *************************************************/ uint16_t BSP_GetCurRecv4Serial1(void) { //等待中的消息队列(通信 接收数据队列) return uxQueueMessagesWaiting(queueRecvData); } /**************************************** * @funName : BSP_SetRecvOffline4Serial1 * @Description : 对数据监听离线状态时间计数进行更新(硬件定时器中执行) * @Athor : YL Software Group * @Version : V0.0.0 * @Data : 2025/4/02 ********************************************/ void BSP_SetRecvOffline4Serial1(void) { ++recv_offline_timer_count; } /********************************************** * @funName : BSP_GetRecvOffline4Serial1 * @Output : 离线状态时间计数 * @Description : 读取数据监听离线状态时间计数(硬件定时器中执行) * @Athor : YL Software Group * @Version : V0.0.0 * @Data : 2025/4/02 *********************************************/ uint16_t BSP_GetRecvOffline4Serial1(void) { return recv_offline_timer_count; } /************************ End of file *************************/ //重定义fputc函数 int fputc(int ch, FILE *f) { while((USART3->SR&0X40)==0);//循环发送,直到发送完毕 USART1->DR = (u8) ch; return ch; } 将STM32F105的代码修改成不用FreeRTOS的队列写入数据,用标准库写出详细实现功能的代码,写清楚注释

#include "stm32f10x.h" //Device header #include "Delay.h" #include "OLED.h" #include "key.h" #include "usart2.h" #include "AS608.h" #include "usart.h" #include "malloc.h" #include "rc522_config.h" #include "rc522_function.h" #include "bsp_SysTick.h" #include "matrix_key_bsp.h" #include "matrix_key.h" #include "PWM.h" #include "Store.h" #include "timer.h" #define usart2_baund 57600//串口2波特率,根据指纹模块波特率更改(注意:指纹模块默认57600) char cStr [ 30 ]; u8 ucArray_ID [ 4 ]; //先后存放IC卡的类型和UID(IC卡序列号) u8 ucStatusReturn; //返回状态 static u8 ucLineCount = 0; SysPara AS608Para;//指纹模块AS608参数 u16 ValidN;//模块内有效模板个数 u16 ID; uint16_t key_value = 0; uint32_t start_time = 0; void Add_FR(void); //录指纹 void Del_FR(void); //删除指纹 void press_FR(void);//刷指纹 void ShowErrMessage(u8 ensure);//显示确认码错误信息 void IC_test (void); uint32_t Get_Tick(void); void SysTick_init (void); uint8_t NonBlocking_Delay(uint32_t start_time, uint32_t interval); uint32_t last_time = 0; // 记录上次时间 int main(void) { uint16_t key_value = 0; uint16_t last_key_value = 0; u8 ensure; char *str; Matrix_Key_Init(); TIM2_Int_Init(); TIM3_Int_Init(); SysTick_Init (); //滴答时钟初始化 SysTick_init (); RC522_Init (); //RC522模块所需外设的初始化配置 SysTick_Init (); //滴答时钟初始化 Servo_Init(); OLED_Init(); Store_Init(); // Store_Data[1]=12345; //防止忘记密码随时可以改你想要的密码 // Store_Save(); //只需要你解除注释然后下载进去,密码就是12345 // Store_Data[2]=1; //同理解除冻结 注意:解除注释录进去后冻结解除,如果需要加入冻结功能 // Store_Save(); // 需要恢复注释再录一遍(试了一个多小时才发现原来是这个问题) char KeyNum; //键码 int last; //错误次数标志位 unsigned int Sum=0; //输入的密码 int password=12345; //初始密码 int Show_Num=40; //OLED显示 int Change=3; // password=Store_Data[1]; //读取flash里的内容 last=Store_Data[2]; int

/****************************************************************************** */ /* //定时器1初始化 void time1_init() { int value=16384; T1CTL = 0x0E; //T1定时器 128 分频,模模式 ; T1CCTL0 |= 0x04; //设定timer1通道0输出比较模式 //设定计数溢出值 T1CC0H = value/256; T1CC0L= value %256; //定时器1中断使能 IEN1|=0X02; //开总中断 EA=1; } //定时器1中断服务程序 #pragma vector = T1_VECTOR __interrupt void T1_ISR(void) { counter++; // 增加计数 EA=0; //关总中断 // 切换LED状态 D3 = !D3; // 切换LED3状态 T1IF = 0; // 清除定时器1中断标志 EA = 1; //开总中断 } */ void StartPeriodicDataCollection(void) { if (!isPeriodicCollectionActive) { isPeriodicCollectionActive = true; HalLedSet(HAL_LED_1, HAL_LED_MODE_BLINK); // LED 状态变化,提示开始采集 // 启动定时器 } } void StopPeriodicDataCollection(void) { if (isPeriodicCollectionActive) { isPeriodicCollectionActive = false; HalLedSet(HAL_LED_1, HAL_LED_MODE_OFF); // LED 状态变化,提示停止采集 // 停止定时器 } } /****************************************************************************** * @fn sendReport * * @brief Send sensor report * * @param none * * @return none */ static void sendReport(void) { uint8 pData[SENSOR_REPORT_LENGTH]; static uint8 reportNr=0; uint8 txOptions; //上报过程中LED灯闪烁一次 HalLedSet( HAL_LED_1, HAL_LED_MODE_OFF ); HalLedSet( HAL_LED_1, HAL_LED_MODE_BLINK ); dht11_update(); collectData(); // Read and report temperature value pData[SENSOR_TEMP_OFFSET] = sTemp; //任意选取的常量 // Read and report voltage value pData[SENSOR_VOLTAGE_OFFSET] = sHumidity; //任意选取的常量 pData[SENSOR_PARENT_OFFSET] = HI_UINT16(parentShortAddr); pData[SENSOR_PARENT_OFFSET + 1] = LO_UINT16(parentShortAddr); // Set ACK request on each ACK_INTERVAL report // If a report failed, set ACK request on next report if ( ++reportNr<ACK_REQ_INTERVAL && reportFailureNr==0 ) { txOptions = AF_TX_OPTIONS_NONE; } else { txOptions = AF_MSG_ACK_REQUEST; reportNr = 0; } // Destination address 0xFFFE: Destination address is sent to previously // established binding for the commandId. //将数据包发送给协调器(协调器的地址为0xFFFE) zb_SendDataRequest( 0xFFFE, SENSOR_REPORT_CMD_ID, SENSOR_REPORT_LENGTH, pData, 0, txOptions, 0 ); } // 每隔2秒采集数据10次后停止采集 void collectData(void) { int collectCount = 0; while (collectCount < 10) { dht11_update(); // 采集数据 void sendReport(); // 将数据发送给B节点 halWait(2); // 等待2秒 collectCount++; } } /****************************************************************************** * @fn zb_ReceiveDataIndication * * @brief The zb_ReceiveDataIndication callback function is called * asynchronously by the ZigBee stack to notify the application * when data is received from a peer device. * * @param source - The short address of the peer device that sent the data * command - The commandId associated with the data * len - The number of bytes in the pData parameter * pData - The data sent by the peer device * * @return none */ void zb_ReceiveDataIndication( uint16 source, uint16 command, uint16 len, uint8 *pData ) { HalLedSet( HAL_LED_1, HAL_LED_MODE_OFF ); //关闭D7 HalLedSet( HAL_LED_1, HAL_LED_MODE_BLINK ); //使D7闪烁 if (len >= strlen("0x131 ON") && strncmp((char *)pData, "0x131 ON", strlen("0x131 ON")) == 0) { // 检查命令是否为"0x131 ON" HalLedSet(HAL_LED_2, HAL_LED_MODE_ON); // 打开D6 } else if (len >= strlen("0x131 OFF") && strncmp((char *)pData, "0x131 OFF", strlen("0x131 OFF")) == 0) { // 检查命令是否为"0x131 OFF" HalLedSet(HAL_LED_2, HAL_LED_MODE_OFF); // 关闭D6 } else if (len >= strlen("0x132") && strncmp((char *)pData, "0x132", strlen("0x132")) == 0) { // 检查命令是否为"0x132"(采集一次数据) sendReport(); // 采集并发送数据 } else if (len >= strlen("0x133") && strncmp((char *)pData, "0x133", strlen("0x133")) == 0) { // 检查命令是否为"0x133"(开始周期性采集) StartPeriodicDataCollection(); // 开始周期性采集 } else if (len >= strlen("0x134") && strncmp((char *)pData, "0x134", strlen("0x134")) == 0) { // 检查命令是否为"0x134"(停止周期性采集) StopPeriodicDataCollection(); // 停止周期性采集 } }修改函数使其满足采集 10 次后,结束采集,进入等待状态的要求

大家在看

recommend-type

生成几何模型-实用非参数统计第三版

(2)设置不显示日期和时间 Utility Menu: PlotCtrls →Window Controls →Window Options→DATE DATE/TIME display: NO DATE or TIME (3) 定义材料参数 Main Menu: Preprocessor → Material Props → Material Models → Material Models Available → Structural(双击打开子菜单) → Linear(双击) → Elastic(双击) → Isotropic(双击) → EX: 7e10(弹性模量) , PRXY:0.288(泊松比) →Density:2700 OK → 关闭材料定义菜单(点击菜单的右上角 X) (4) 选择单元类型 Main Menu: Preprocessor → Element Type → Add/Edit/Delete → Add… → Library of element Types: Structural Solid, Quad 4node 42 → OK → Add → Library of element Types: Structural Solid, Brick 8node 45 →OK → Add → Library of Types: Structural Shell, Elastic 4node 63 →OK (5) 定义实常数 Main Menu: Preprocessor → Real Constants → Add/Edit/Delete → Add → Choose element type: Type3 Shell63 → OK → Real Constant Set No:1 (第 1 号实常数), Shell thickness at node I:0.005 node J: 0.005 node K: 0.05 node L: 0.05 (厚度) → OK → Close (6) 生成几何模型 Step1 生成六边形 Main Menu: Preprocessor → Modeling → Create →Areas → Polygon → Hexagon → WP X:0, WP Y:0, Radious: 0.4 → OK Step2 旋转工作平面 Utility Menu: WorkPlane →Offset WP by Increments → XY,YZ,ZX Angles:30 →OK   Step4 生成矩形 Main Menu→Preprocessor→Modeling→Create →Areas→Rectangle→By 2 Corners→WPX:0.3; WPY: -0.2 ;Width:1.8464, Hight:0.4 →OK   Step5 转换坐标系 Utility Menu: WorkPlane→Change Active CS to→Global Cylindrical   Step6 复制矩形 Main Menu: Preprocessor →Modeling →Copy →Areas→鼠标点击选择面 2,即帆板面 →OK number of copys:3 ;DY:120→OK   Step7 面搭接 Main Menu: Preprocessor →Modeling →Operate →Booleans →Overlap →Areas→ pick all →OK 应用实例 IV-4
recommend-type

aefsdr efs解密工具

可以进行efs解密的好用软件,帮助大家解决丢失密匙的问题
recommend-type

FT2232串口驱动.rar

FT2232串口驱动,支持win系统,用于usb转串口,安装即可使用,在开发中具有重要的用途,欢迎下载
recommend-type

ISO 6469-3-2021 电动道路车辆 - 安全规范 - 第 3 部分:电气安全.docx

国际标准,txt格式 本文件规定了电力推进系统电压 B 级电路和电动道路车辆导电连接辅助电力系统的电气安全要求。 它规定了保护人员免受电击和热事故的电气安全要求。 它没有为制造、维护和维修人员提供全面的安全信息。 注 1: 碰撞后的电气安全要求在 ISO 6469-4 中有描述。 注 2:ISO 17409 描述了电动道路车辆与外部电源的导电连接的电气安全要求。 注 3: 外部磁场无线功率传输的特殊电气安全要求 在 ISO 19363 中描述了电力供应和电动车辆。 注 4 摩托车和轻便摩托车的电气安全要求在 ISO 13063 系列中有描述。 2 引用标准 以下文件在文中的引用方式是,其部分或全部内容构成本文件的要求。对于注明日期的参考文献,只有引用的版本适用。对于未注明日期的引用,引用文件的最新版本 (包括任何修订) 适用。 ISO 17409: 电动道路车辆。导电动力传输。安全要求 ISO 20653,道路车辆 - 保护程度 (IP 代码)- 电气设备防异物、水和接触的保护 IEC 60664 (所有部件) 低压系统内设备的绝缘配合 IEC 60990:2016,接触电流和保护导体
recommend-type

我的CJK 李果正 简体

学习latex CJK的好教程,这个是简体中方版本,作者是台湾的李果正

最新推荐

recommend-type

信息学奥赛简介NOIP及C++基础知识夏令营第一天顺序语句.ppt

信息学奥赛简介NOIP及C++基础知识夏令营第一天顺序语句.ppt
recommend-type

8FSK-报告--基于matlab汇总.doc

8FSK-报告--基于matlab汇总.doc
recommend-type

Android移动应用试题(带答案).doc

Android移动应用试题(带答案).doc
recommend-type

Linux文件信息命令和基本文件管理.pdf

Linux文件信息命令和基本文件管理.pdf
recommend-type

游戏开发中的中文输入法IME实现与应用

从给定文件信息来看,我们主要关注的领域集中在如何在游戏开发中实现输入法编辑器(IME)来支持汉字输入。由于这个话题与编程实践紧密相关,我们将展开以下几个方面的知识点:IME的工作原理、游戏开发中实现IME的一般方法、以及中文输入法相关的编程资源。 IME(输入法编辑器)是一种软件工具,允许用户输入汉字和其他亚洲语言的字符。它提供了比标准键盘布局更高效的方式输入文字。由于游戏开发中可能需要支持多语言,其中包含中文用户的需求,因此实现一个稳定的IME支持至关重要。 ### IME工作原理 IME的实现是基于Unicode编码标准。当用户输入一个拼音时,IME会将这个拼音转换成一个或多个汉字候选,用户随后可以从候选列表中选择合适的汉字。此过程涉及以下步骤: 1. **拼音输入**:用户通过键盘输入拼音。 2. **拼音转换**:IME将输入的拼音转换成对应的汉字候选列表。 3. **选择与确认**:用户从候选列表中选择想要的汉字,然后确认输入。 ### 游戏开发中的IME实现 在游戏中实现IME,需要考虑如何将IME集成到游戏界面中,并确保用户输入的流畅性和正确性。以下是一些关键步骤和考虑事项: 1. **选择合适的开发平台和工具**:不同的游戏开发平台(如Unity、Unreal Engine等)可能提供不同的支持和接口来集成IME。 2. **集成IME组件**:开发人员需要将IME组件集成到游戏的用户界面中。这涉及到游戏引擎提供的UI系统以及可能的第三方IME库。 3. **处理键盘事件**:需要捕捉用户的键盘输入事件,并将其传递给IME进行处理。 4. **显示候选词窗口**:当用户输入拼音后,游戏需要能够显示一个候选词窗口,并在窗口中列出汉字候选。 5. **选择和确认机制**:游戏需要提供机制允许用户选择并确认输入的汉字,以及在必要时进行错误修正。 6. **性能优化**:IME的处理可能会消耗系统资源,因此需要进行适当的优化以保证游戏运行流畅。 ### 中文输入法相关的编程资源 从给定的文件名称列表中,我们可以得知有一些与“GameRes_com”相关的资源。尽管文件的具体内容未提供,我们可以推测这些资源可能是关于如何在游戏中实现中文输入法的示例代码或者库文件。通常,这些资源可能包括: 1. **GameRes_com.htm**:可能是一个HTML文件,其中包含关于IME集成的说明文档,或者是相关代码的参考文档。 2. **GameRes_com.files**:可能是一组文件,包含必要的类定义、资源文件、图像、样式表等,这些都可以被整合进游戏工程来支持中文输入。 3. **ime**:这可能是一个目录,里面包含了实现IME功能所需的所有资源,包括脚本、配置文件以及第三方库等。 ### 总结 在游戏开发中实现IME以支持汉字输入是一个复杂的过程,它不仅涉及到对开发环境和工具的深入理解,还需要考虑如何优化用户输入体验。由于中文用户的特殊需求,游戏开发者需要将IME集成到游戏中,并确保这一过程对玩家而言无缝且直观。以上提供的文件名称表明有一些现成的资源可以被利用,开发者可以通过阅读文档、示例代码或直接使用相关资源来快速实现这一功能。由于具体内容未提供,开发者还需要关注到细节实现的调整,以及针对特定游戏引擎或平台的开发指南。
recommend-type

【性能测试基准】:为RK3588选择合适的NVMe性能测试工具指南

# 1. NVMe性能测试基础 ## 1.1 NVMe协议简介 NVMe,全称为Non-Volatile Memory Express,是专为固态驱动器设计的逻辑设备接口规范。与传统的SATA接口相比,NVMe通过使用PCI Express(PCIe)总线,大大提高了存储设备的数据吞吐量和IOPS(每秒输入输出操作次数),特别适合于高速的固态存储设备。
recommend-type

implicit declaration of function 'Complementary_Init' [-Wimplicit-function-declaration] 这个报错是什么意思

<think>我们遇到了一个编译错误:`implicitdeclarationoffunction'Complementary_Init'`。这个错误表示在调用函数`Complementary_Init`时,编译器没有找到它的声明(即函数原型)。在C语言中,如果函数在使用之前没有被声明,编译器会按照旧的C标准(如C89)假设该函数返回`int`类型,并且参数类型根据实际调用进行推断。但在C99及以后的标准中,这种隐式声明是不允许的,因此会报错。###错误原因分析根据引用[2]的分析,出现`implicitdeclarationoffunction`错误通常有以下几种原因:1.**函数未声明**
recommend-type

MATLAB图像分析新手入门教程

MATLAB是一种高性能的数值计算和可视化软件,广泛应用于工程计算、控制设计、信号处理和通信等众多领域。在图像分析领域,MATLAB提供了强大的工具箱,使得图像处理和分析变得简单高效。本文将详细解析MATLAB在图像分析中的应用,并提供相关资源下载链接。 首先,需要明确MATLAB图像分析主要集中在以下几个方面: 1. 图像读取与显示:MATLAB提供了诸如`imread`、`imshow`等函数,可以很方便地读取和显示图像。`imread`可以读取不同格式的图像文件,而`imshow`则用于显示这些图像。对于初学者而言,掌握这些基础函数是进行图像分析的前提。 2. 图像类型和格式:MATLAB支持多种图像格式,如常见的`.jpg`、`.png`、`.bmp`等。不同格式图像的数据结构在MATLAB中可能有所不同,例如彩色图像和灰度图像的像素数据表示。了解不同图像格式的特点及其在MATLAB中的表示,对于后续的图像处理至关重要。 3. 图像基本操作:MATLAB可以进行图像的裁剪、缩放、旋转、平移等基本操作。例如,使用`imcrop`函数裁剪图像,`imresize`函数调整图像大小等。掌握这些操作对于图像预处理尤为重要。 4. 图像变换:包括傅立叶变换、离散余弦变换等。MATLAB中的`fft2`、`dct2`等函数可以实现这些变换。图像变换是图像分析中非常重要的一个环节,可以帮助我们从不同角度理解图像信息。 5. 图像增强:图像增强主要目的是改善图像的视觉效果,包括对比度调整、锐化、滤波去噪等。MATLAB中的`imadjust`、`fspecial`、`imfilter`等函数可以实现这些操作。 6. 图像分割:在图像分析中,将感兴趣的物体从背景中分割出来是常见需求。MATLAB提供了如`imsegfuzz`、`regionprops`等函数,帮助用户完成图像分割任务。 7. 特征提取与分析:MATLAB能够提取图像特征(如纹理、形状、颜色等),并进行统计分析。例如,使用`graythresh`进行阈值分割,`edge`函数进行边缘检测等。 8. 图像识别与分类:基于提取的特征,MATLAB可以利用机器学习算法对图像进行识别和分类。如使用MATLAB的机器学习工具箱中的`fitcknn`等函数来训练分类器。 通过使用MATLAB进行图像分析,可以实现从简单到复杂的各种图像处理任务。针对初学者,文件包中的“使用帮助:新手必看.htm”提供了入门指导,帮助新手快速理解MATLAB在图像处理方面的基本知识和操作;而“Matlab中文论坛--助努力的人完成毕业设计.url”可能指向一个在线论坛或社区,提供交流和求助的平台;“face_detection”表示该文件可能包含与人脸识别相关的示例代码或者教程。 对于初学者来说,MATLAB图像分析的难点往往在于对图像处理算法的理解和实际应用的结合。在实际操作中,建议从简单的图像读取与显示开始,逐步深入到图像处理的各个方面。同时,利用MATLAB强大的工具箱和社区资源,通过示例学习和实践,可以在实践中不断提升自身的图像分析能力。 上述文件包中提供的“face_detection”文件,很可能是一个关于人脸检测的应用示例。人脸检测作为图像分析中的一个重要领域,在计算机视觉和模式识别中占有重要地位。MATLAB在这一领域的工具箱如Computer Vision Toolbox提供了人脸检测的现成函数和算法,可以高效地帮助开发者完成人脸检测任务。 总结以上所述,MATLAB图像分析的知识点包括图像读取显示、格式转换、基本操作、变换、增强、分割、特征提取和图像识别分类等多个方面。对于初学者来说,通过实践操作和案例学习,可以逐步掌握这些知识,并应用到实际问题解决中。同时,利用好MATLAB提供的各种资源和社区,可以更快地学习和进步。
recommend-type

【固态硬盘寿命延长】:RK3588平台NVMe维护技巧大公开

# 1. 固态硬盘寿命延长的基础知识 ## 1.1 固态硬盘的基本概念 固态硬盘(SSD)是现代计算设备中不可或缺的存储设备之一。与传统的机械硬盘(HDD)相比,SSD拥有更快的读写速度、更小的体积和更低的功耗。但是,SSD也有其生命周期限制,主要受限于NAND闪存的写入次数。 ## 1.2 SSD的写入次数和寿命 每块SSD中的NAND闪存单元都有有限的写入次数。这意味着,随着时间的推移,SSD的
recommend-type

Reg.exe add "HKLM\SOFTWARE\Microsoft\DirectX" /v "DXGI_PREEMPTION_MODE" /t REG_DWORD /d "3" /f Reg.exe add "HKLM\SOFTWARE\Microsoft\DirectX" /v "DXGI_FRAME_LATENCY_WAITABLE_OBJECT" /t REG_DWORD /d "1" /f Reg.exe add "HKLM\SOFTWARE\Microsoft\DirectX" /v "DXGI_SWAP_CHAIN_WAITABLE_OBJECT" /t REG_DWORD /d "1" /f Reg.exe add "HKLM\SOFTWARE\Microsoft\DirectX" /v "DXGI_FORCE_FLIP_DISCARD" /t REG_DWORD /d "1" /f Reg.exe add "HKLM\SOFTWARE\Microsoft\DirectX" /v "DXGI_SWAP_CHAIN_SCALE" /t REG_DWORD /d "1" /f Reg.exe add "HKLM\SOFTWARE\Microsoft\DirectX" /v "DXGI_SWAP_CHAIN_ALLOW_MODE_SWITCH" /t REG_DWORD /d "1" /f Reg.exe add "HKLM\SOFTWARE\Microsoft\DirectX" /v "DXGI_SWAP_CHAIN_FULLSCREEN_FLIP_MODE" /t REG_DWORD /d "1" /f Reg.exe add "HKLM\SOFTWARE\Microsoft\DirectX" /v "DXGI_DISABLE_DWM_THROTTLING" /t REG_DWORD /d "1" /f Reg.exe add "HKLM\SOFTWARE\Microsoft\DirectX" /v "DXGI_FORCE_FLIP_SEQUENTIAL" /t REG_DWORD /d "1" /f Reg.exe add "HKLM\SOFTWARE\Microsoft\DirectX" /v "DXGI_FORCE_FULLSCREEN_FLIP_MODE" /t REG_DWORD /d "3" /f Reg.exe add "HKLM\SOFTWARE\Microsoft\DirectX" /v "DXGI_MAX_FRAME_LATENCY" /t REG_DWORD /d "2" /f Reg.exe add "HKLM\SOFTWARE\Microsoft\DirectX" /v "DXGI_USE_OPTIMIZED_SWAP_CHAIN" /t REG_DWORD /d "1" /f 这些注册表值有什么用,逐一解答

<think>我们正在讨论DirectX相关的注册表值。用户询问的是DXGI_PREEMPTION_MODE、DXGI_FRAME_LATENCY_WAITABLE_OBJECT、DXGI_SWAP_CHAIN_WAITABLE_OBJECT等的作用。注意:这些注册表值可能是用于调试或特定配置的,但并不是标准的DXGI公开接口。因此,它们可能不是官方文档中明确说明的,而是内部使用的或者特定驱动/调试设置。根据我的知识,这些值并不常见于公开文档,但我们可以尝试根据名称和上下文进行解释,并参考一些开发经验。1.DXGI_PREEMPTION_MODE:-这个注册表值可能与GPU抢占(Preempt