采用CH32F103C8T6做下位机,上位机用SSCOM连续向下位机发送查询指令,下位机上传几次数据后就不再上传数据了,只在USART1有此问题,USART2没有这个问题,同样的架构的程序移植到CH32VF103也正常没有出现这个情况,这个是硬件本身的问题吗,可有解决办法,程序随附件
- /*******************************************************************************
- * [url=home.php?mod=space&uid=288409]@file[/url] cmd_usart.c
- * [url=home.php?mod=space&uid=187600]@author[/url] MR.Hu
- * [url=home.php?mod=space&uid=895143]@version[/url] 0.0.1
- * [url=home.php?mod=space&uid=212281]@date[/url] 2021-07-18
- * [url=home.php?mod=space&uid=247401]@brief[/url] 命令串口使用
- *********************************************************************************************/
- /*--------包含的头文件--------------------------------------------------------------------------*/
- #include <string.h>
- #include "cmd_usart.h"
- #include "global_variables.h"
- #include "CRC8_16.h"
- /*--------中断声明-----------------------------------------------------------------------------*/
- void USART1_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
- void USART2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
- /*--------全局变量-----------------------------------------------------------------------------*/
- /**********************************************************************************************
- * 函数名 : uart_init()
- * 形参变量 :bound-------波特率
- * 返回值 :无
- * 函数功能 :串口1初始化
- *********************************************************************************************/
- void cmd_uart_init(uint32_t CMD_USART_Baudrate)
- {
- //-------GPIO端口设置--------------------------------------------------
- GPIO_InitTypeDef GPIO_InitStructure;
- USART_InitTypeDef USART_InitStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
- USART_DeInit(USART1); //复位串口1
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);
- //------USART1_TX PA.9-------------------------------------------------------------------------------
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; // PA.9
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
- GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化PA9
- //------USART1_RX PA.10------------------------------------------------------------------------------
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; // 初始化PA10
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- // 485收发控制管脚
- RCC_APB2PeriphClockCmd(RS485_RE_GPIO_CLK,ENABLE); //开启按键端口的时钟
- GPIO_InitStructure.GPIO_Pin = RS485_RE_PIN;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(RS485_RE_GPIO_PORT, &GPIO_InitStructure);
- GPIO_ResetBits(RS485_RE_GPIO_PORT,RS485_RE_PIN); // 控制485芯片进入接收模式
- //------Usart1 NVIC 配置-------------------------------------------------------------------------------
- USART_InitStructure.USART_BaudRate = CMD_USART_Baudrate; // 设置波特率
- USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 设置字长
- USART_InitStructure.USART_StopBits = USART_StopBits_1; // 1位停止位
- USART_InitStructure.USART_Parity = USART_Parity_No; // 没有校验位
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 无硬件流控制
- USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; // 双工模式
- USART_Init(USART1, &USART_InitStructure);
- // 空闲中断设置
- NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 抢占优先级为1
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 子优先级为1
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // IRQ通道使能
- NVIC_Init(&NVIC_InitStructure); // 中断优先级初始化
- // USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); // 接收中断使能
- USART_ITConfig(USART1,USART_IT_IDLE,ENABLE); // 串口空闲中断使能
- USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
- USART_Cmd(USART1,ENABLE);
- }
- /**********************************************************************************************
- * 函数名 : uart_init()
- * 形参变量 :bound-------波特率
- * 返回值 :无
- * 函数功能 :串口1初始化
- *********************************************************************************************/
- void device_usart_init(uint32_t DEVICE_USART_Baudrate)
- {
- //-------GPIO端口设置--------------------------------------------------
- GPIO_InitTypeDef GPIO_InitStructure;
- USART_InitTypeDef USART_InitStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
- USART_DeInit(USART2); //复位串口1
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
- //------USART2_TX PA.2-------------------------------------------------------------------------------
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; // PA.9
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
- GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化PA9
- //------USART1_RX PA.3------------------------------------------------------------------------------
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; // 初始化PA10
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- //------Usart1 NVIC 配置-------------------------------------------------------------------------------
- USART_InitStructure.USART_BaudRate = DEVICE_USART_Baudrate; // 设置波特率
- USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 设置字长
- USART_InitStructure.USART_StopBits = USART_StopBits_1; // 1位停止位
- USART_InitStructure.USART_Parity = USART_Parity_No; // 没有校验位
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 无硬件流控制
- USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; // 双工模式
- USART_Init(USART2, &USART_InitStructure);
- // 空闲中断设置
- NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 抢占优先级为1
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 子优先级为1
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // IRQ通道使能
- NVIC_Init(&NVIC_InitStructure); // 中断优先级初始化
- // USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); // 接收中断使能
- USART_ITConfig(USART2,USART_IT_IDLE,ENABLE); // 串口空闲中断使能
- USART_DMACmd(USART2, USART_DMAReq_Rx, ENABLE);
- USART_Cmd(USART2,ENABLE);
- }
- /*******************************************************************************
- * Function Name : DMA1_CH5_Init
- * Description : Initializes Channel3 of DMA1 collection. DMA1通道5传输参数配置
- * Input : None
- * Return : None
- *******************************************************************************/
- void DMA1_CH5_USART1_RX_Init(void)
- {
- DMA_InitTypeDef DMA_InitStructure;
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // 使能DMA1时钟
- DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DATAR); // 设置源数据地址
- DMA_InitStructure.DMA_MemoryBaseAddr = (u32) CMD_RX_Buffer; // 设置目标地址
- DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; // 设置传输方向:外设到存储器(此处外设为内部FLASH)
- DMA_InitStructure.DMA_BufferSize = CMD_RX_Buf_Len; // 设置传输大小
- 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_PeripheralDataSize_Byte; // 设置存储器数据单位
- DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; // 设置对应DMA工作模式为正常模式
- DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; // DMA1通道5优先级高
- DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; // 使能DMA存储器到存储器的传输方式
- DMA_Init(DMA1_Channel5, &DMA_InitStructure); // 根据DMA_InitStruct中指定的参数初始化DMA1通道3
- DMA_Cmd(DMA1_Channel5, ENABLE); // 使能DMA1通道5
- }
- /*******************************************************************************
- * Function Name : DMA1_CH5_Init
- * Description : Initializes Channel3 of DMA1 collection. DMA1通道5传输参数配置
- * Input : None
- * Return : None
- *******************************************************************************/
- void DMA1_CH6_USART2_RX_Init(void)
- {
- DMA_InitTypeDef DMA_InitStructure;
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // 使能DMA1时钟
- DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART2->DATAR); // 设置源数据地址
- DMA_InitStructure.DMA_MemoryBaseAddr = (u32) DEVICE_RX_Buffer; // 设置目标地址
- DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; // 设置传输方向:外设到存储器(此处外设为内部FLASH)
- DMA_InitStructure.DMA_BufferSize = CMD_RX_Buf_Len; // 设置传输大小
- 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_PeripheralDataSize_Byte; // 设置存储器数据单位
- DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; // 设置对应DMA工作模式为正常模式
- DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; // DMA1通道5优先级高
- DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; // 使能DMA存储器到存储器的传输方式
- DMA_Init(DMA1_Channel6, &DMA_InitStructure); // 根据DMA_InitStruct中指定的参数初始化DMA1通道3
- DMA_Cmd(DMA1_Channel6, ENABLE); // 使能DMA1通道6
- }
- void DMA1_Init(void)
- {
- DMA1_CH5_USART1_RX_Init();
- DMA1_CH6_USART2_RX_Init();
- }
- /**********************************************************************************************
- * 函数名 :Usart1_Send()
- * 形参变量 :无
- * 返回值 :无
- * 函数功能 :串口1发送程序
- *********************************************************************************************/
- void Usart1_Send(uint8_t *buf, uint16_t len)
- {
- uint16_t t;
- RS485_TX_EN();
- for(t=0;t<len;t++) // 循环发送数据
- {
- while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); // TXE 弹夹为空
- USART_SendData(USART1,buf[t]);
- }
- while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET); // TC,弹夹为空,枪膛也为空
- RS485_RX_EN();
- }
- /*******************************************************************************
- * 函数名 :Usart2_Send()
- * 形参变量 :无
- * 返回值 :无
- * 函数功能 :串口2发送程序
- *******************************************************************************/
- void Usart2_Send(uint8_t *buf, uint16_t len)
- {
- uint16_t t;
- for(t=0;t<len;t++) // 循环发送数据
- {
- while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
- USART_SendData(USART2,buf[t]);
- }
- while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
- }
- /**********************************************************************************************
- * 函数名 :USARTx_SendByte()
- * 形参变量 :pUSARTx,可以是USART1、USART2、USART3
- * data,要发送的字节
- * 返回值 :无
- *函数功能 :串口发送字符串
- *********************************************************************************************/
- void USARTx_SendByte(USART_TypeDef* pUSARTx, uint8_t data)
- {
- while(USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
- USART_SendData(pUSARTx, data);
- while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
- }
- /**********************************************************************************************
- * 函数名 :USARTx_SendStr()
- * 形参变量 :pUSARTx: 可以是USART1、USART2、USART3
- * *str : 字符串
- * 返回值 :无
- *函数功能 :串口发送字符串
- *********************************************************************************************/
- void USARTx_SendStr(USART_TypeDef* pUSARTx, char *str)
- {
- uint8_t i = 0;
- RS485_TX_EN();
- do
- {
- USARTx_SendByte(pUSARTx, *(str+i));
- i++;
- }while(*(str+i) != '\0');
- while(USART_GetFlagStatus(pUSARTx, USART_FLAG_TC) == RESET);
- RS485_RX_EN();
- }
- void USART2_SendStr(char *str)
- {
- uint8_t i = 0;
- do
- {
- USARTx_SendByte(USART2, *(str+i));
- i++;
- }while(*(str+i) != '\0');
- while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
- }
- /**********************************************************************************************
- * 函数名 :USART1_IRQHandler()
- * 形参变量 :无
- * 返回值 :无
- *函数功能 :串口1中断服务程序
- *********************************************************************************************/
- void USART1_IRQHandler(void)
- {
- if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)
- {
- DMA_Cmd(DMA1_Channel5,DISABLE); // 关闭DMA传输
- CMD_USART_Rec_Cnt = CMD_RX_Buf_Len - DMA_GetCurrDataCounter(DMA1_Channel5); // 获取串口接收的数据数量
- Receive_one_fame_OK = 1; // 1帧数据完成接收
- //-----------------------------------------------------------------------------------------------------------------------------------------//
- // USART1->STATR; // 读状态寄存器
- // USART1->DATAR; // 再读数据寄存器,此操作用于清除空闲中断标志位
- DMA_SetCurrDataCounter(DMA1_Channel5,CMD_RX_Buf_Len); // 重新设置传输的数据数量
- DMA_Cmd(DMA1_Channel5,ENABLE); // 开启DMA传输
- USART_ReceiveData(USART1); // 读取一次数据,不然会一直进中断
- USART_ClearFlag(USART1,USART_FLAG_IDLE); // 清除串口空闲中断标志位
- }
- }
- /**********************************************************************************************
- * 函数名 :USART1_IRQHandler()
- * 形参变量 :无
- * 返回值 :无
- *函数功能 :串口1中断服务程序
- *********************************************************************************************/
- void USART2_IRQHandler(void)
- {
- uint16_t CRC_calchkval;
- if(USART_GetITStatus(USART2, USART_IT_IDLE) != RESET)
- {
- DMA_Cmd(DMA1_Channel6,DISABLE); // 关闭DMA传输
- DEVICE_USART_Rec_Cnt = CMD_RX_Buf_Len - DMA_GetCurrDataCounter(DMA1_Channel6); // 获取串口接收的数据数量
- DEVICE_USART_Receive_complete = 1; // 1帧数据完成接收
- //--------------------------------------------------------------------------------//
- CMD_TX_Buffer[0] =HEAD_FRAME_HI; // 帧头高位
- CMD_TX_Buffer[1] =HEAD_FRAME_LO; // 帧头低位
- CMD_TX_Buffer[2] =BOARD_ADDRESS; // 电路模块地址
- CMD_TX_Buffer[3] = functional_unit; // 功能单元,同一地址的电路模块中的某个器件,00表示回复数据为版本号
- CMD_TX_Buffer[4] = functional_code; // 功能码
- CMD_TX_Buffer[5] =((uint8_t)((DEVICE_USART_Rec_Cnt & 0xFF00)>>8)); // 数据长度
- CMD_TX_Buffer[6] =((uint8_t)( DEVICE_USART_Rec_Cnt & 0x00FF)); // 数据长度
- memcpy(CMD_TX_Buffer+7,DEVICE_RX_Buffer,DEVICE_USART_Rec_Cnt); // 数据保存在第二个缓冲区
- CRC_calchkval = MODBUS_CRC16(CMD_TX_Buffer, 7+DEVICE_USART_Rec_Cnt);
- CMD_TX_Buffer[7+DEVICE_USART_Rec_Cnt] = ((uint8_t)(( CRC_calchkval & 0xFF00)>>8));// 校验码保存到待发送的缓存里
- CMD_TX_Buffer[8+DEVICE_USART_Rec_Cnt] = ((uint8_t)( CRC_calchkval & 0x00FF) );
- Usart1_Send(CMD_TX_Buffer,9+DEVICE_USART_Rec_Cnt);
- DMA_SetCurrDataCounter(DMA1_Channel6,CMD_RX_Buf_Len); // 重新设置传输的数据数量
- DMA_Cmd(DMA1_Channel6,ENABLE); // 开启DMA传输
- USART_ReceiveData(USART2); // 读取一次数据,不然会一直进中断
- USART_ClearFlag(USART2,USART_FLAG_IDLE); // 清除串口空闲中断标志位
- }
- }
|
|