写在前面

在2020年电子设计竞赛中我们要完成的任务是做一辆可循黑白间隔线的电动爬坡小车,题目如下:

因为当时我们用的MSP430F5529芯片只有4个定时器,一个产生电机PWM,一个产生舵机PWM,还有一个做定时中断使用,而后面2路的正交解码信号也需要2个定时中断进行解码,因此我使用了2块Ti芯片,芯片A进行正交解码,并且以波特率115200通过串口将数据传输给芯片B,由芯片B进行小车外设的控制,那么两块芯片之间的通信方式就非常重要了,不但要做到准确,而且延迟不能太高

准确是因为芯片B需要利用编码器数据控制电机转速,如果编码器数据错了的话直接导致电机转飞,这是很危险的。延迟不能很高也是这个原因,通信总是会有一些时间误差,相当于现在用于电机控制的速度是上一次的反馈量,这样的误差也是比较危险的,也是有可能会导致电机转飞的。所以今天这篇博客主要将我是如何利用MSP430F5529芯片进行双芯片通信的

PulseCnt

这个文件夹里面主要是副芯片读取出编码器数据之后通过串口以波特率115200将数据传给主芯片。

我们先来看一下编码器发送数据的方法,具体实现如下图所示:

__interrupt void TIMER1_B0_IRQ_Handler()
{    
    static uint8_t led_cnt = 0;
    g_left_value = TIMER_Pluse_GetValue(TIMER_A1,g_left_over_flow);
    if(GPIO_ReadBit(P2,0) == 0){
        g_left_value *= -1;
    }
    g_right_value = TIMER_Pluse_GetValue(TIMER_A0,g_right_over_flow);
    if(GPIO_ReadBit(P1,7) == 1){
        g_right_value *= -1;
    }
    UART_Printf(UART0,"L%d:",g_left_value);
    UART_Printf(UART0,"R%d;",g_right_value);
    g_left_value = 0;
    g_right_value = 0;
    g_left_over_flow = 0;              //清除溢出次数
    g_right_over_flow = 0;
    TIMER_Pluse_Clear(TIMER_A1);
    TIMER_Pluse_Clear(TIMER_A0);
    if(led_cnt ++ == 4){
        led_cnt = 0;
        LED_Turn(LED1);
    }
}

因为轮子是有正反转的区别的,因此在传输的时候要考虑‘-’,这个符号主要是在接收的时候要特殊处理一下。

MainCore

在主芯片中主要是做串口数据的接收以及解码处理,我是在主芯片的中断里面接收串口数据的:

__interrupt void UART0_RX_IRQ_Handler()
{ 
    static uint8_t record_L = 0;
    static uint8_t record_R = 0;

  if(UART_GetITStatus(UART0,UART_RX_IRQn) == TRUE)   //清除串口某一个中断标志
  {
    uart0_data = UART_GetChar(UART0);
    if(uart0_data == 'L'){ 
        g_left_ok = 0;
    }
    else if(uart0_data == 'R'){  
        g_right_ok = 0;
    }else if(uart0_data == ':'){
        g_left_pulese_array[record_L] = '_';
        record_L = 0;
        g_left_ok = 1;
    }else if(uart0_data == ';'){
        g_right_pulese_array[record_R] = '|';
        record_R = 0;
        g_right_ok = 1;
    }else{
        if(g_left_ok == 0){
            g_left_pulese_array[record_L] = uart0_data;
            record_L++;
        }else if(g_right_ok == 0){
            g_right_pulese_array[record_R] = uart0_data;
            record_R++;
        }
    }
    UART_ClearITPendingBit(UART0,UART_RX_IRQn);    //清除串口某一个中断标志
  }
}

我们先来看一下主芯片接收到的数据帧格式:


因为我是一个个字符接收数据,所以会在接收的时候自动把‘R’和‘L’给过滤掉,并且添加新的数据帧头‘_’,接收到了数据之后就是对数据做二次处理了:

void GetPulse()
{
    int left_neg = 1;
    int right_neg = 1;
    uint8_t left_first_0;
    uint8_t right_first_0;

    g_left_pulse = 0;
    g_right_pulse = 0;

    for(uint8_t i = 0 ; i < PULSEARRAY;i++){
      if(g_right_pulese_array[i] == '0' && right_first_0 == 0){
        right_first_0 = 1;
      }
      else if(g_right_pulese_array[i] == '-'){

        right_neg = -1;
      }else if(g_right_pulese_array[i] == '|'){

        g_right_pulse *= right_neg;
        break;
      }else{
        g_right_pulse = g_right_pulse * 10 + (g_right_pulese_array[i] - '0');
      }
    }

     for(uint8_t i = 0 ; i < PULSEARRAY;i++){
      if(g_left_pulese_array[i] == '0' && left_first_0 == 0){
        left_first_0 == 1;
      }
      else if(g_left_pulese_array[i] == '-'){
        left_neg = -1;
      }else if(g_left_pulese_array[i] == '_'){
        g_left_pulse *= left_neg;
        break;
      }else{
        g_left_pulse = g_left_pulse * 10 + (g_left_pulese_array[i] - '0');
      }
    }

    if(encoder_integral == 1 || encoder_integral == 3){
        encoder_sum += (g_left_pulse + g_right_pulse) / 2;
    }

    for(uint8_t i = 0 ; i < PULSEARRAY;i++){
        g_right_pulese_array[i] = '0';
    }
    for(uint8_t i = 0 ; i < PULSEARRAY;i++){
        g_left_pulese_array[i] = '0';
    }

}

最后的encoder_sum就是后面两个轮子的平均速度
以上这段程序在我的公众号AIplusX里面的程序资料的RampCar文件夹里,具体位置看这个: