FR801XH 使用串1做打印,且可以接受用户手工发送数据包过去 修改参数!



    1. 实际上我不建议大家用RX FIFO去处理串口接收,除非是定长协议包,而实际是非定长数据包协议居多,且要考虑丢字节情况下,如何快速应对。我的建议代码如下:
      //串口中断函数 我们配置接收字节中断试试
      volatile struct uart_reg_t *uart1_reg = (volatile struct uart_reg_t *)UART1_BASE;
      attribute((weak)) attribute((section("ram_code"))) void timer1_isr_ram(void)
      {
      timer_clear_interrupt(TIMER1);
      uart0_info.rxd_flg = 0;
      printf("uart0 timeout !!!!!!!!! \r\n");
      timer_stop(TIMER1);
      }

    attribute((weak)) attribute((section("ram_code"))) void uart0_isr_ram(void)
    {
    uint8_t int_id;
    uint8_t rx_byte;

    int_id = uart0_reg->u3.iir.int_id;
    

    timer_stop(TIMER1);
    if(int_id == 0x04 || int_id == 0x0c ) /* Receiver data available or Character time-out indication */
    {
    rx_byte = uart0_reg->u1.data;
    uart0_info.packet_timeout = 2;
    if(1 == uart0_info.rxd_flg)
    {
    uart0_info.rxd_buf[uart0_info.rxd_ctr++] = rx_byte; //
    if(uart0_info.rxd_ctr == uart0_info.rxd_len)
    { //收齐 处理包
    uart0_info.rxd_ctr = 0;
    uart0_info.rxd_flg = 0;
    uart0_info.rxd_cmd_len = uart0_info.rxd_len;
    memcpy(uart0_info.rxd_cmd_buf, uart0_info.rxd_buf, uart0_info.rxd_len);
    evt.event_id = 0; //串口0 事件
    os_msg_post(uart01_task_id, &evt);
    }
    else if(3==uart0_info.rxd_ctr)
    {
    uart0_info.rxd_len = rx_byte + 4;//后面字节包的长度
    }
    else ;
    }
    else //== 0
    {
    if(0xA7 == rx_byte) //协议包头
    {
    uart0_info.rxd_flg = 1; //开启接收
    uart0_info.rxd_ctr = 1; //接收字节计数
    uart0_info.rxd_buf[0] = rx_byte;
    }
    }
    }
    else if(int_id == 0x06)
    {
    volatile uint32_t line_status = uart0_reg->lsr;
    }
    else if(int_id == 0x02)
    {
    if(uart0_info.txd_ctr < uart0_info.txd_len[uart0_info.txd_busy_index]) //判断当前包是否发送完毕
    {
    uart0_reg->u1.data = uart0_info.txd_buf[uart0_info.txd_busy_index][uart0_info.txd_ctr++];
    }
    else //发完一包 休息或继续下一包
    {
    uart0_info.txd_len[uart0_info.txd_busy_index] = 0; //清除发送包长度 表示空的 可以重新组装
    if(uart0_info.txd_len[uart0_info.txd_emptypp_index]>0) //有包要发 则继续
    {
    if(0==uart0_info.txd_busy_index) {
    uart0_info.txd_busy_index = 1;
    uart0_info.txd_emptypp_index = 0;
    }
    else {
    uart0_info.txd_busy_index = 0;
    uart0_info.txd_emptypp_index = 1;
    }
    uart0_info.txd_ctr = 1;
    uart0_reg->u1.data = 0xA7; //
    }
    else
    {
    uart0_reg->u2.ier.eti = 0;
    uart0_info.tx_busy = IDLE;
    }
    }
    }
    else ;
    if(uart0_info.rxd_flg)
    {
    timer_set_current_value(TIMER1, 0);
    timer_run(TIMER1);
    }
    }

    对于有DMA发送的MCU 发送可以用DMA中断,我的这个字节发送中断 适用于更多MCU,缺点是每发1个字节,就会进串口发送结束中断1次。
    严重注意: 串口接收 需要在系统设计中来的及处理,否则出现了溢出OE这些异常,记得代码里要写下清标志,否则单片就就会一直卡死这中断里,最后等看门狗复位了。

    1. SDK V1.0.8版本 在汇编 app_boot_vectors.S 里 把串口1中断函数入口 给屏蔽了,且名字不是uart1_isr_ram
      大家注意修改 import uart1_isr_ram
      DCD uart1_isr_ram ; 4 2个地方 这样串口1就可以进入中断函数入口了

    建议大家初始化串口1 还是放在SDK原来这个位置
    void user_entry_before_ble_init(void)
    {
    ......
    // Enable UART print.
    system_set_port_pull(GPIO_PA2, true);
    system_set_port_mux(GPIO_PORT_A, GPIO_BIT_2, PORTA2_FUNC_UART1_RXD);
    system_set_port_mux(GPIO_PORT_A, GPIO_BIT_3, PORTA3_FUNC_UART1_TXD);
    uart_init(UART1, BAUD_RATE_115200);
    uart_init(UART1, BAUD_RATE_2400); //即热模块 2400波特率
    NVIC_SetPriority(UART1_IRQn, 1);
    NVIC_EnableIRQ(UART1_IRQn);
    ..................
    }

    上述使能了,串口1不但可以打印,还可以中断方式 接收字节,用于调试。 因为目前芯片的DEBUG固件存在 一定概率无法仿真的情况,(我用的是FR8018HA 其他型号不知道)

    3、 目前存在问题: 定时器1的 字节超时, 我测试过定时器1 设置1S 定时间隔 都对,但是做10ms字节超时 就经常进中断,导致我丢包,我之前用了其他GD32 DA等 arm单片机 用1个定时器给1个串口做字节超时 都没发生过。但是示例1的字节超时总是打断正常收包。 我2个字节发送间隔肯定小于 超时时间的。 这个问题不得而知,耽误了我2天,很奇怪。 所以我只能做 包超时了!!



  • 您好请问,用12m有什么好处?



  • @鱼的记忆 我的应用比较简单,采用12M系统运行频率,可以比24M降低几ma 功耗。我的市电断电下,是靠锂电池作为备用电源,蓝牙芯片一直运行不睡眠。



  • 好的,谢谢。。。。。但是这样传输速率也变低了



  • 他这个可以做睡眠的,等他接收完就睡眠,这个可以由发射端控制睡眠



  • @鱼的记忆 发射端控制睡眠? 我的蓝牙做为外设(服务端),需要广播,手机APP作为client端。



  • 我以为你的蓝牙是作为从机,作为从机就可以这样做,