问答

汇集网友智慧,解决技术难题

21ic问答首页 - TAG - 485
  • GD32E230用捕获及485通讯,开启捕获就通讯卡死且初始化失败 sos

    GD32E230C8T6 用TIMER2_CH3进行频率捕获,同时用USART0进行485通讯,一开启捕获就通讯不了,且一点仿真DEBUG按钮就直接全速运行,然后就卡死在LDR R0, =SystemInit位置,无法初始化。具体代码如下: int main(void){ systick_config(); //滴答定时器初始化 Led_Gpio_Init(); //数码管引脚初始化 Key_Init(); //按键引脚初始化 Relay_GPIO_Init(); //继电器引脚初始化 Capture_Gpio_config(); //捕获引脚初始化 usart_config(9600); //串口配置 Para_Read(); //读取参数 LedPower = 1; //电源灯亮 Adc_gpio_config(); //ADC采样引脚初始化 Adc_Config(); //ADC参数配置初始化 Nvic_config(); //捕获中断 Timer2_config(); //Timer2配置 Timer5_Init(3600,40); //定时10ms = 3600/72M *200 Timer14_Init(36,625); //定时312.5us while(1) { Adc_Cal(); //ADC采样计算 fre_capture_cal(); KeyMake(); //按键动作 Protect(); Display(); //显示 UartDriver(); } } void Capture_Gpio_config(void) { /* 使能GPIOB时钟 */ rcu_periph_clock_enable(RCU_GPIOB); /* 配置PB1(TIMER2_CH3)为复用功能 */ gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_1); gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_1); gpio_af_set(GPIOB, GPIO_AF_1, GPIO_PIN_1); // 根据数据手册选择正确的AF } /* ********************************************************************************************************* * 函 数 名: nvic_config * 功能说明: 配置中断优先级 * 形 参:无 * 返 回 值: 无 ********************************************************************************************************* */ void Nvic_config(void) { nvic_irq_enable(TIMER2_IRQn,0); } /* ********************************************************************************************************* * 函 数 名: timer2_config * 功能说明: 定时器配置--捕获 * 形 参:无 * 返 回 值: 无 ********************************************************************************************************* */ void Timer2_config(void) { timer_ic_parameter_struct timer_icinitpara; timer_parameter_struct timer_initpara; /* enable the TIMER clock */ rcu_periph_clock_enable(RCU_TIMER2); /* disable a TIMER */ timer_deinit(TIMER2); /* initialize TIMER init parameter struct */ timer_struct_para_init(&timer_initpara); /* TIMER2 configuration */ timer_initpara.prescaler = 7199; timer_initpara.alignedmode = TIMER_COUNTER_EDGE; timer_initpara.counterdirection = TIMER_COUNTER_UP; timer_initpara.period = 65535; timer_initpara.clockdivision = TIMER_CKDIV_DIV1; timer_init(TIMER2, &timer_initpara); /* TIMER2 configuration */ /* initialize TIMER channel input parameter struct */ timer_channel_input_struct_para_init(&timer_icinitpara); /* TIMER2 CH3 input capture configuration */ timer_icinitpara.icpolarity = TIMER_IC_POLARITY_RISING; //此处采用下降沿捕获, TIMER_IC_POLARITY_RISING timer_icinitpara.icselection = TIMER_IC_SELECTION_DIRECTTI; timer_icinitpara.icprescaler = TIMER_IC_PSC_DIV1; timer_icinitpara.icfilter = 0x0; timer_input_capture_config(TIMER2,TIMER_CH_3,&timer_icinitpara); /* auto-reload preload enable */ timer_auto_reload_shadow_enable(TIMER2); /* clear channel 3 interrupt bit */ timer_interrupt_flag_clear(TIMER2,TIMER_INT_FLAG_CH3 ); /* clear channel 3 interrupt bit */ timer_interrupt_flag_clear(TIMER2,TIMER_INT_FLAG_UP ); /* channel 3 interrupt enable */ timer_interrupt_enable(TIMER2,TIMER_INT_CH3); /* channel 3 interrupt enable */ timer_interrupt_enable(TIMER2,TIMER_INT_UP); /* TIMER2 counter enable */ timer_enable(TIMER2); } /* ********************************************************************************************************* * 函 数 名: TIM2_IRQHandler * 功能说明: TIM2 中断服务程序 * 形 参:无 * 返 回 值: 无 1us ********************************************************************************************************* */ void TIMER2_IRQHandler(void) { if(timer_interrupt_flag_get(TIMER2,TIMER_INT_FLAG_CH3)) { timer_interrupt_flag_clear(TIMER2,TIMER_INT_FLAG_CH3); //清除TIMER2的中断标志 uint32_t currentCapture = timer_channel_capture_value_register_read(TIMER2,TIMER_CH_3); if(firstCapture) { lastCapture = currentCapture; firstCapture = 0; } else { capture_diff = (currentCapture - lastCapture) +(overflow_count * 65536); test_flag = 1; //置位测量标志 lastCapture = currentCapture; } overflow_count = 0; } if(timer_interrupt_flag_get(TIMER2,TIMER_INT_FLAG_UP)) { timer_interrupt_flag_clear(TIMER2,TIMER_INT_FLAG_UP); overflow_count ++; } } void fre_capture_cal(void) { if(test_flag) { test_flag = 0; frequency = 10000.0f/capture_diff; MeasData.freq = (uint32_t)(frequency*10); //频率转换 } if(MeasData.Uln < 50) //小于5V { MeasData.freq = 0; } } void usart_config(uint32_t band_rate) { rcu_periph_clock_enable(RCU_GPIOA); // 开启引脚端口时钟 PA9 TX PA10 RX rcu_periph_clock_enable(RCU_USART0); // 开启串口时钟 /* 配置GPIO复用功能 */ gpio_af_set(GPIOA, GPIO_AF_1, GPIO_PIN_9); gpio_af_set(GPIOA, GPIO_AF_1, GPIO_PIN_10); /* 配置PA9 TX为复用模式 上拉模式 */ gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_9); /* 配置TX为推挽输出 50MHZ */ gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9); /* 配置PA10 RX为复用模式 无上拉下拉模式 */ gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_10); /* 配置RX为浮空输入 50MHZ */ gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10); /* 配置DE为输出模式 无上拉下拉模式 */ gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_11); //485 /* 配置DE为推挽输出 50MHZ */ gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_11); //485 RS485_DE(0); //使能接收 485 usart_deinit(USART0); // 复位串口 usart_baudrate_set(USART0,band_rate); // 设置波特率 usart_parity_config(USART0,USART_PM_NONE); // 没有校验位 usart_word_length_set(USART0,USART_WL_8BIT); // 8位数据位 usart_stop_bit_set(USART0,USART_STB_2BIT); // 2位停止位 /* 使能串口 */ usart_receive_config(USART0,USART_RECEIVE_ENABLE); // 使能串口接收 usart_transmit_config(USART0,USART_TRANSMIT_ENABLE); // 使能串口发送 usart_receiver_timeout_threshold_config(USART0,100); //设置串口接收超时阈值,这个100是指100bit时间,如果按照10bit传输一个字节,那么就是10个字节时间 usart_receiver_timeout_enable(USART0); //超时使能 usart_enable(USART0); // 使能串口 nvic_irq_enable(USART0_IRQn,0); usart_interrupt_enable(USART0, USART_INT_RBNE); // 使能接收中断 usart_interrupt_enable(USART0, USART_INT_RT); //使能串口接收超时中断 } void usart_send(uint8_t *buf, uint8_t len) { uint8_t i; while(tx_busy); //等待上一个发送完成 tx_busy = 1; //准备发送 RS485_DE(1); //发送模式 usart_interrupt_disable(USART0, USART_INT_RBNE|USART_INT_RT); // 禁能接收中断(避免发送期间接收自己的数据) for(i=0; i= sizeof(g_recv_buff)) { g_recv_length = 0; } } else if(RESET != usart_interrupt_flag_get(USART0,USART_INT_FLAG_RT)) //接收中断超时标志 { usart_flag_clear(USART0,USART_FLAG_RT); g_recv_complete_flag = 1; } } void UartDriver(void) { uint8_t len; uint8_t buf[64] = {0x00}; //接收数据存放的数组 if(g_recv_complete_flag ==1) { g_recv_complete_flag = 0; process_modbus_request(); g_recv_length = 0; } } void process_modbus_request(void) { uint16_t i = 0; uint16_t j = 0; uint16_t crc = 0; //校验码 uint8_t crch = 0; //校验码高字节 uint8_t crcl = 0; //校验码低字节 uint16_t addr = 0; //寄存器地址 uint16_t cnt = 0; //数据量 uint16_t data = 0; //写入的数据 uint16_t addrtemp = 0; uint16_t index; if(g_recv_buff[0] != Para.Addr ) {return;} crc = usMBCRC16(g_recv_buff,g_recv_length-2); //校验码 crch = (uint8_t)(crc >>8); //取高8位 crcl = (uint8_t)crc; //取低位 if((g_recv_buff[g_recv_length-2]!=crch)||(g_recv_buff[g_recv_length-1]!=crcl)) //校验码不对 { return ; //返回空白值 } addr = ((uint16_t)g_recv_buff[2]<<8)|g_recv_buff[3]; //寄存器地址 switch(g_recv_buff[1]) { /*03功能码 读单个寄存器*/ case 0x03: cnt= ((uint16_t)g_recv_buff[4]<<8)|g_recv_buff[5]; if(cnt==0) //数据量=0 { Errcmd_addr_data(g_recv_buff,3); //返回数据错误码 03 return; } if((addr >= 0x0A00)&&(addr <= 0x0A04)) //地址范围0x0a00--0x0a06 { if((addr+cnt) > 0x0A05) { Errcmd_addr_data(g_recv_buff,3); //字节数超范围,报83错误码 return; } else { for(i=0;i>8); //取高8位数据 (uint8_t)强制转换为uint8_t类型的数据;*取后面括号里的数据 (uint32_t*)把Uln的地址强制转化为uint32_t类型指针 &取Uln的地址 txbuffer[4+i*2] = (uint8_t)(*((uint32_t*)& MeasData.Uln +(addr & 0x00FF)+i)); //取低8位数据 } } } else if((addr >= 0x0B00)&&(addr <= 0x0B13)) //地址范围0x0b00--0x0b07 { if(((addr+cnt) > 0x0B14)||(addr%2 !=0)) //超出地址、地址不等于8的倍数 则报错 { Errcmd_addr_data(g_recv_buff,3); //字节数超范围,报83错误码 return; } else { for(i=0;i>8); //取高8位数据 txbuffer[4+i*2] = (uint8_t)(*((uint32_t*)& Err_ASK.ErrType +((addr & 0x00FF)+i)%2)); //取低8位数据 } } } else if((addr >= 0x0C00)&&(addr <= 0x0C0B)) //地址范围0x0C00--0x0C0B { if((addr+cnt) > 0x0C0C) { Errcmd_addr_data(g_recv_buff,3); //字节数超范围,则报83错误码 return; } else { for(i=0;i>8); //取高8位数据 txbuffer[4+i*2] = (uint8_t)(*((uint32_t*)& Para.Mode +(addr & 0x00FF)+i)); //取低8位数据 } } } else //地址不在范围内,报82错误码 { Errcmd_addr_data(g_recv_buff,2); return; } txbuffer[0] = Para.Addr; //设备地址 txbuffer[1] = 0x03; //功能码 txbuffer[2] = cnt*2; //读出的字节数 crc = usMBCRC16(txbuffer,cnt*2+3); //CRC校验值计算 crch = (uint8_t)(crc >> 8); crcl = (uint8_t)crc; txbuffer[3 + cnt * 2] = crch; //CRC高位数据地址 txbuffer[4 + cnt * 2] = crcl; //CRC低位数据地址 usart_send(txbuffer,cnt*2+5); //发送 break; default: Errcmd_addr_data(g_recv_buff,1); //错误码01 break; } } 有类似遇到的问题吗?求解,谢谢

    失败 485 通讯 GD32E230 TI ar

    881浏览量 0回复量 关注量
  • 485AB对地电平和AB差分电平的疑问 赏100家园币

    发送数据时,485的A对地电压在0-5V,B对地电压也在0-5V,AB对地都是正波形,但是AB差分测得的压差是10V,为什么AB的压差不是5V呢?

    485 AB

    25607浏览量 8回复量 关注量