网站开发设计流程图建个公司网站怎么弄
2026/4/17 0:42:57 网站建设 项目流程
网站开发设计流程图,建个公司网站怎么弄,十大卖衣服网站,郑州知名做网站公司有哪些汽车电子和工业控制的神经系统第一部分#xff1a;CAN总线核心概念CAN是什么#xff1f;CAN#xff08;Controller Area Network#xff09;就像汽车的神经系统#xff1a;双线差分#xff1a;CAN_H和CAN_L两根线#xff0c;抗干扰强多主架构神经系统第一部分CAN总线核心概念CAN是什么CANController Area Network就像汽车的神经系统双线差分CAN_H和CAN_L两根线抗干扰强多主架构任何节点都可以主动发送数据优先级仲裁ID小的优先发送不会冲突广播通信一个发所有节点都能收CAN数据帧结构| 帧起始 | ID(11/29位) | 控制场 | 数据场(0-8字节) | CRC | 应答 | 帧结束 |标准帧11位ID最多2032个不同ID扩展帧29位ID最多5.36亿个不同ID数据长度0-8字节短小高效第二部分代码分块详细解释块1CAN初始化配置/* CAN初始化函数 - 配置CAN控制器基本参数 */ CAN_HandleTypeDef hcan1; // 定义CAN1的句柄用于管理所有CAN配置 void CAN1_Init(void) { CAN_FilterTypeDef can_filter; // 定义过滤器结构体用于筛选接收的消息 // 1. 使能CAN时钟 __HAL_RCC_CAN1_CLK_ENABLE(); // 打开CAN1的时钟外设需要时钟才能工作 __HAL_RCC_GPIOA_CLK_ENABLE(); // 打开GPIOA时钟CAN引脚在PA11、PA12 // 2. 配置CAN引脚 GPIO_InitTypeDef gpio_init; gpio_init.Pin GPIO_PIN_11 | GPIO_PIN_12; // PA11: CAN_RX, PA12: CAN_TX gpio_init.Mode GPIO_MODE_AF_PP; // 复用推挽输出模式 gpio_init.Pull GPIO_NOPULL; // 不启用上下拉电阻 gpio_init.Speed GPIO_SPEED_FREQ_HIGH; // 高速模式 gpio_init.Alternate GPIO_AF9_CAN1; // 复用功能9对应CAN1 HAL_GPIO_Init(GPIOA, gpio_init); // 应用GPIO配置 // 3. 配置CAN工作模式 hcan1.Instance CAN1; // 使用CAN1控制器 hcan1.Init.Mode CAN_MODE_NORMAL; // 正常工作模式 hcan1.Init.AutoBusOff DISABLE; // 禁用自动离线恢复 hcan1.Init.AutoWakeUp DISABLE; // 禁用自动唤醒 hcan1.Init.AutoRetransmission ENABLE; // 启用自动重传 hcan1.Init.ReceiveFifoLocked DISABLE; // 不锁定接收FIFO hcan1.Init.TransmitFifoPriority DISABLE; // 禁用发送邮箱优先级 hcan1.Init.SyncJumpWidth CAN_SJW_1TQ; // 同步跳转宽度1个时间单元 hcan1.Init.TimeSeg1 CAN_BS1_9TQ; // 时间段1为9个时间单元 hcan1.Init.TimeSeg2 CAN_BS2_4TQ; // 时间段2为4个时间单元 hcan1.Init.Prescaler 6; // 预分频值决定波特率 // 计算波特率: APB1时钟36MHz, 36MHz/(6*(194)) 36MHz/(6 * 14) 428.5kHz HAL_CAN_Init(hcan1); // 应用CAN配置 // 4. 配置CAN过滤器 can_filter.FilterIdHigh 0x0000; // 过滤器ID高16位 can_filter.FilterIdLow 0x0000; // 过滤器ID低16位 can_filter.FilterMaskIdHigh 0x0000; // 掩码高16位 can_filter.FilterMaskIdLow 0x0000; // 掩码低16位 can_filter.FilterFIFOAssignment CAN_RX_FIFO0; // 接收到的数据存到FIFO0 can_filter.FilterBank 0; // 使用过滤器0 can_filter.FilterMode CAN_FILTERMODE_IDMASK; // 标识符屏蔽位模式 can_filter.FilterScale CAN_FILTERSCALE_32BIT; // 32位过滤器 can_filter.FilterActivation ENABLE; // 启用过滤器 can_filter.SlaveStartFilterBank 14; // 从过滤器库起始编号 HAL_CAN_ConfigFilter(hcan1, can_filter); // 应用过滤器配置 // 5. 启动CAN HAL_CAN_Start(hcan1); // 启动CAN控制器 // 6. 使能接收中断 HAL_CAN_ActivateNotification(hcan1, CAN_IT_RX_FIFO0_MSG_PENDING); }块2CAN数据发送/* 发送CAN数据帧 - 封装要发送的数据 */ uint8_t CAN_Send_Msg(uint32_t id, uint8_t *data, uint8_t len) { uint32_t mailbox; // 邮箱编号CAN有3个发送邮箱 CAN_TxHeaderTypeDef tx_header; // 定义发送帧头结构体 // 1. 检查数据长度是否合法 if (len 8) { // CAN帧最多8字节数据 return 1; // 返回1表示错误: 数据过长 } // 2. 配置发送帧头 tx_header.StdId id; // 标准帧ID11位0x000-0x7FF tx_header.ExtId 0; // 扩展帧ID标准帧时为0 tx_header.IDE CAN_ID_STD; // 标识符类型: 标准帧 tx_header.RTR CAN_RTR_DATA; // 帧类型: 数据帧不是远程帧 tx_header.DLC len; // 数据长度码0-8字节 tx_header.TransmitGlobalTime DISABLE; // 不发送全局时间 // 3. 将数据加入发送邮箱 // HAL_CAN_AddTxMessage参数: // hcan1: CAN句柄 // tx_header: 帧头配置 // data: 要发送的数据数组 // mailbox: 返回使用的邮箱号(0,1,2) if (HAL_CAN_AddTxMessage(hcan1, tx_header, data, mailbox) ! HAL_OK) { return 2; // 返回2表示错误: 加入邮箱失败 } // 4. 等待发送完成 // 轮询检查发送完成标志 while (HAL_CAN_IsTxMessagePending(hcan1, mailbox)); return 0; // 返回0表示发送成功 }块3CAN数据接收中断方式/* CAN接收中断回调函数 - 收到数据时自动调用 */ uint8_t rx_data[8]; // 接收数据缓冲区 uint32_t rx_id; // 接收到的ID uint8_t rx_len; // 接收到的数据长度 CAN_RxHeaderTypeDef rx_header; // 接收帧头 // 中断回调函数 void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) { // 1. 从FIFO0读取一帧数据 // HAL_CAN_GetRxMessage参数: // hcan: CAN句柄 // CAN_RX_FIFO0: 从FIFO0读取 // rx_header: 存储帧头信息 // rx_data: 存储数据 HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, rx_header, rx_data); // 2. 获取接收到的信息 if (rx_header.IDE CAN_ID_STD) { // 判断是标准帧 rx_id rx_header.StdId; // 获取标准ID } else { // 扩展帧 rx_id rx_header.ExtId; // 获取扩展ID } rx_len rx_header.DLC; // 获取数据长度 // 3. 根据ID处理不同数据示例 switch (rx_id) { case 0x100: // ID 0x100: 转速信息 Process_Engine_Speed(rx_data); // 处理发动机转速 break; case 0x200: // ID 0x200: 温度信息 Process_Temperature(rx_data); // 处理温度数据 break; case 0x300: // ID 0x300: 开关状态 Process_Switch_Status(rx_data); // 处理开关状态 break; default: // 其他ID Process_Other_Msg(rx_data); // 处理其他消息 break; } }块4CAN数据接收轮询方式/* 轮询方式接收CAN数据 - 在主循环中调用 */ uint8_t CAN_Receive_Msg(uint8_t *data, uint32_t *id) { CAN_RxHeaderTypeDef rx_header; // 接收帧头 // 1. 检查FIFO0是否有新消息 if (HAL_CAN_GetRxFifoFillLevel(hcan1, CAN_RX_FIFO0) 0) { // 2. 从FIFO0读取消息 if (HAL_CAN_GetRxMessage(hcan1, CAN_RX_FIFO0, rx_header, data) HAL_OK) { // 3. 获取ID if (rx_header.IDE CAN_ID_STD) { *id rx_header.StdId; // 标准帧ID } else { *id rx_header.ExtId; // 扩展帧ID } return rx_header.DLC; // 返回数据长度 } } return 0; // 返回0表示没有数据 }块5应用示例 - 汽车转速发送/* 发送发动机转速到CAN总线 */ void Send_Engine_Speed(uint16_t rpm) { uint8_t can_data[8]; // CAN数据缓冲区 uint8_t data_len 2; // 数据长度: 2字节 // 1. 准备要发送的数据 // 将16位转速拆分成2个字节 can_data[0] (rpm 8) 0xFF; // 高字节 can_data[1] rpm 0xFF; // 低字节 // 2. 填充其余字节为0可选 for (uint8_t i data_len; i 8; i) { can_data[i] 0x00; // 未使用的字节填0 } // 3. 发送CAN消息 // ID: 0x100 表示发动机数据 // 数据: can_data数组 // 长度: data_len if (CAN_Send_Msg(0x100, can_data, data_len) 0) { // 发送成功 LED_Toggle(); // 可添加LED指示发送成功 } else { // 发送失败处理 Error_Handler(); } }第三部分CAN通信完整示例/* 文件: can_communication.c * 功能: 完整的CAN通信示例包含发送和接收 * 硬件: STM32F103 TJA1050 CAN收发器 * 功能: 模拟汽车ECU通信 */ #include main.h #include can.h #include stdio.h // 全局变量 CAN_HandleTypeDef hcan1; uint8_t tx_data[8], rx_data[8]; uint32_t tx_id 0x100, rx_id 0; uint8_t tx_len 8, rx_len 0; int main(void) { // 1. 初始化系统 HAL_Init(); // 初始化HAL库 SystemClock_Config(); // 配置系统时钟 MX_GPIO_Init(); // 初始化GPIO MX_CAN1_Init(); // 初始化CAN1 // 2. 启动CAN和中断 HAL_CAN_Start(hcan1); HAL_CAN_ActivateNotification(hcan1, CAN_IT_RX_FIFO0_MSG_PENDING); // 3. 主循环 while (1) { // 3.1 发送引擎转速示例 static uint16_t engine_rpm 0; engine_rpm (engine_rpm 10) % 8000; // 模拟转速变化 uint8_t data[2]; data[0] (engine_rpm 8) 0xFF; data[1] engine_rpm 0xFF; CAN_Send_Msg(0x100, data, 2); // 发送转速 // 3.2 轮询接收其他ECU数据 rx_len CAN_Receive_Msg(rx_data, rx_id); if (rx_len 0) { // 处理接收到的数据 Process_Received_Data(rx_id, rx_data, rx_len); } // 3.3 延时 HAL_Delay(100); // 100ms发送一次 } } /* CAN接收中断回调函数 */ void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) { CAN_RxHeaderTypeDef rx_header; // 读取接收到的消息 HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, rx_header, rx_data); // 获取ID rx_id (rx_header.IDE CAN_ID_STD) ? rx_header.StdId : rx_header.ExtId; rx_len rx_header.DLC; // 根据ID处理示例 switch (rx_id) { case 0x200: // 车速信息 uint16_t speed (rx_data[0] 8) | rx_data[1]; printf(车速: %d km/h\n, speed); break; case 0x201: // 水温信息 uint8_t temp rx_data[0]; printf(水温: %d C\n, temp); if (temp 100) { Send_Warning(0x01); // 发送高温警告 } break; default: break; } }第四部分CAN通信核心要点总结1. CAN配置步骤记忆口诀时钟引脚先使能波特率要算精准 模式参数配置好过滤器是守门人 启动中断别忘了收发数据靠轮询2. 波特率计算公式CAN波特率 APB1时钟 / (预分频 * 时间单元总数) 时间单元总数 1(同步段) BS1 BS2 例如 APB1时钟 36MHz 预分频 6 BS1 9, BS2 4 波特率 36MHz / (6 * (194)) 428.5kbps3. 过滤器配置模式模式作用应用场景标识符列表模式​精确匹配几个ID只接收特定ID的消息标识符屏蔽位模式​按位过滤ID接收某一类ID的消息4. 常见问题排查现象可能原因解决方法CAN发送失败波特率不匹配检查两端波特率设置接收不到数据过滤器配置错误检查过滤器ID和掩码错误帧太多终端电阻未接CAN_H和CAN_L加120Ω电阻通信不稳定线路干扰使用双绞线远离干扰源发送邮箱满发送太快增加发送间隔或检查发送完成标志5. 实际应用技巧// 技巧1: 快速计算DLC对应的数据长度 // CAN的DLC编码特殊8有特殊含义 uint8_t get_data_length(uint8_t dlc) { if (dlc 8) return dlc; // 对于CAN FDDLC编码不同 return 8 (dlc - 8) * 4; } // 技巧2: 扩展帧发送 void send_extended_frame(uint32_t ext_id, uint8_t* data, uint8_t len) { CAN_TxHeaderTypeDef tx_header; tx_header.ExtId ext_id; // 29位扩展ID tx_header.IDE CAN_ID_EXT; // 扩展帧 // ... 其他配置相同 } // 技巧3: 远程帧请求 void send_remote_frame(uint32_t id) { CAN_TxHeaderTypeDef tx_header; tx_header.StdId id; tx_header.RTR CAN_RTR_REMOTE; // 远程帧 tx_header.DLC 0; // 远程帧数据长度为0 // ... 发送配置 }6. 学习建议从标准帧开始先掌握11位ID的标准帧用逻辑分析仪抓取CAN波形理解帧结构分步调试先调通发送再调接收模拟多节点用两块开发板互相通信参考真实协议学习CANopen、J1939等上层协议记住CAN总线是优先级仲裁的不是主从式的。任何节点都可以在总线空闲时发送ID小的优先级高。这是CAN与I2C、SPI最大的区别

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询