通信

在上一次的灵动微课堂中和大家分享过MM32F013x-UART 9bit通信实例,本次微课堂在此实例的基础上实现UART多处理器通信。MM32F013x系列MCU支持UART多处理器通信,其工作原理是主从机设备采用复用漏极开路,主从机外部接上拉电阻,在空闲时使从机处于静默模式,主机要控制从机执行任务时主机发送指令唤醒从机并发送数据控制从机执行相应任务。

1、UART静默模式

MM32F013x系列MCU UART静默模式的特点

  • 任何接收状态位都不会被设置
  • 所有的接收中断都被禁止
  • UART_CCR寄存器中的RWU位被置1。RWU可以被硬件自动控制或在某个条件下由软件写入。

根据UART_CCR寄存器中的WAKE位状态,UART多处理器通信有二种方法进入或退出静默模式分别是:

  • WAKE 位被设置0:进行空闲总线检测。
  • WAKE 位被设置1:进行地址标记检测。

空闲总线检测

空闲帧唤醒可以同时唤醒所有从机,在从机处于静默模式时主机发送空闲帧(即所有位均为1的数据)实现多个从机同步被唤醒。

地址标记检测

地址标记唤醒可以唤醒单个从机,从机进入静默模式时,主机向从机寻址发送地址帧,从机自动比对地址,地址配对正确则该从机被唤醒,否则继续进入静默模式。这样只有被主机寻址的从机才被唤醒激活并接收数据,从而减少未被寻址的从机参与带来的多余的UART服务开销。

2、配置流程

与UART多处理器通信相关的主要寄存器有UART通用控制寄存器、UART接收地址寄存器UART_RXADDR和UART接收掩码寄存器UART_RXMASK其描述如下寄存器表所示:

图1

如上图1所示为UART通用控制寄存器UART_CCR,在MM32F013x UM手册的第489和第490页有关于该寄存器位的详细描述。本实例UART多处理器通信要用到的相关于UART通用控制寄存器UART_CCR位的说明如下:

Bit13

WAKE(rw,reset:0x00)唤醒方法,该位决定UART多机通信从机唤醒的方法。

1:地址标记唤醒。
库函数设置:
UART_WakeUpConfig(UART1,UART_WakeUp_AddressMark);

0:空闲总线唤醒。
库函数设置:
UART_WakeUpConfig(UART1, UART_WakeUp_IdleLine);

Bit12

RWU(rw, reset:0x00)接收唤醒,该位用来决定是否把UART置于静默模式。该位可以由软件设置或清除。当唤醒序列到来时,硬件也会自动将其清零。

1:接收器处于静默模式。
库函数设置:
UART_ReceiverWakeUpCmd(UART1, ENABLE);

0:接收器处于正常工作模式。
库函数设置:
UART_ReceiverWakeUpCmd(UART1, DISABLE);

注:在设置地址标记唤醒时,如果接收 buffer 非空则不能软件修改。

Bit11

B8EN(rw, reset:0x00)UART同步帧发送第9bit使能控制位。该位使能后校验使能PEN不起作用。

1:使能同步帧第9bit发送。
库函数设置:
UART_Enable9bit(UART1, ENABLE);

0:禁止同步帧第9bit发送。
库函数设置:
UART_Enable9bit(UART1, DISABLE);

Bit10

B8TOG(rw,reset:0x00)UART同步帧发送第9bit自动翻转控制位。

1:使能第9bit自动翻转。
库函数设置:
UART_Set9bitAutomaticToggle(UART1, ENABLE);

0:禁止第9bit自动翻转。
库函数设置:

UART_Set9bitAutomaticToggle(UART1, DISABLE);
注:在 B8TXD 和 B8POL 的值相同时,在配置完寄存器后传输的第二个数据开始翻转,第一个数据默认为地址位。

Bit8

B8TXD(rw,reset:0x00)UART同步帧发送数据第9bit。

1:发送同步帧第9bit为高电平。
库函数设置:
UART_Set9bitLevel(UART1, ENABLE);

0:发送同步帧第9bit为低电平。
库函数设置:
UART_Set9bitLevel(UART1, DISABLE)

图2

如上图2所示为UART接收地址寄存器UART_RXADDR,在MM32F013x UM手册的第491页有关于该寄存器位的详细描述。本实例UART多处理器通信要用到的相关于UART_RXADDR接收地址寄存器位的说明如下:

Bit31:8:

Reserved,始终读为0x00

Bit7:0:

RXADDR(rw,reset:0x00)UART 同步帧数据本机匹配地址。

库函数设置:
UART_SetRXAddress(UART1, SLAVEADDR);

其中地址参数SLAVEADDR可以设置为宏定义形式。

如果 RXMASK =0xFF时接收到的同步帧数据与本机匹配地址相同时,产生RXB8_INTF。地址 0是广播地址,收到后都会响应。

图3

如上图3所示为UART接收掩码寄存器UART_RXMASK,在MM32F013x UM手册的第492页有关于该寄存器位的详细描述。本实例UART多处理器通信要用到的相关于UART_RXMSK接收掩码寄存器位的说明如下:

Bit31:8:

Reserved,始终读为0x00

Bit7:0:

RXMASK(rw,reset:0xFF)UART数据位全为“0”时,接收到任何数据都产生同步帧中断请求。如果数据位为“1”,RDR和RXADDR的相应位匹配时,产生同步帧中断请求。

库函数设置:

UART_SetRXMASK(UART1,SLAVEADDR); 其中地址参数SLAVEADDR可以设置为宏定义形式。

根据上文与UART 9bit多处理器通信相关的寄存器位的描述,本实例从机唤醒模式使用标记从机地址方式,在MM32F013x-UART 9bit通信实例的基础上增加从机UART 9bit多处理器通信相关的寄存器位的初始化,这里以库函数方式给出,增加的4行代码如下所示:

//Wake up method
UART_WakeUpConfig(UART1, UART_WakeUp_AddressMark);
//Synchronous frame match address
UART_SetRXAddress(UART1, SLAVEADDR);
//Synchronous frame match address mask
UART_SetRXMASK(UART1,SLAVEADDR);
//Receive wake up method
UART_ReceiverWakeUpCmd(UART1, ENABLE);

3、程序配置

01、初始化主机MM32F013x UART1 9bit通信

本实例使用MM32F0133C7P核心板作为UART多处理器通信,主机初始化代码如下所示:

bsp_UART1_Master_irq_9Bit_Init(u32 baudrate)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    UART_InitTypeDef UART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOA, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_UART1, ENABLE);

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);

    GPIO_StructInit(&GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    UART_StructInit(&UART_InitStructure);
    UART_InitStructure.BaudRate = baudrate;
    UART_InitStructure.WordLength = UART_WordLength_8b;
    UART_InitStructure.StopBits = UART_StopBits_1;
    UART_InitStructure.Parity = UART_Parity_No;
    UART_InitStructure.HWFlowControl = UART_HWFlowControl_None;
    UART_InitStructure.Mode = UART_Mode_Rx | UART_Mode_Tx;

    UART_Enable9bit(UART1, ENABLE);
    UART_Set9bitLevel(UART1, DISABLE);
    UART_Set9bitAutomaticToggle(UART1, ENABLE);
    UART_Init(UART1, &UART_InitStructure);

    UART_ITConfig(UART1, UART_IT_RXIEN, ENABLE);

    NVIC_InitStructure.NVIC_IRQChannel = UART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPriority = 3;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    UART_Cmd(UART1, ENABLE);
}

02、初始化从机MM32F013x UART1 9bit通信

MM32F0133C7P UART1从机初始化代码如下所示:

注意:多从机通信,初始化从机串口时需要修改从机地址宏为0x01、0x02等。

#define SLAVEADDR  (0x01)
void bsp_UART1_Slave_irq_9Bit_Init(u32 baudrate)
{
   GPIO_InitTypeDef GPIO_InitStructure;
   UART_InitTypeDef UART_InitStructure;
   NVIC_InitTypeDef NVIC_InitStructure;

   RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOA, ENABLE);
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_UART1, ENABLE);

   GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);
   GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);

   GPIO_StructInit(&GPIO_InitStructure);
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
   GPIO_Init(GPIOA, &GPIO_InitStructure);

   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
   GPIO_Init(GPIOA, &GPIO_InitStructure);

   UART_StructInit(&UART_InitStructure);
   UART_InitStructure.BaudRate = baudrate;
   UART_InitStructure.WordLength = UART_WordLength_8b;
   UART_InitStructure.StopBits = UART_StopBits_1;
   UART_InitStructure.Parity = UART_Parity_No;
   UART_InitStructure.HWFlowControl = UART_HWFlowControl_None;
   UART_InitStructure.Mode = UART_Mode_Rx | UART_Mode_Tx;

   UART_WakeUpConfig(UART1, UART_WakeUp_AddressMark);
   UART_WakeUpConfig(UART1, UART_WakeUp_IdleLine);
   UART_SetRXAddress(UART1, SLAVEADDR);
   UART_SetRXMASK(UART1,0x02);
   UART_ReceiverWakeUpCmd(UART1, ENABLE);
   UART_Enable9bit(UART1, ENABLE);
   UART_Set9bitLevel(UART1, DISABLE);
   UART_Set9bitAutomaticToggle(UART1, ENABLE);
   UART_Init(UART1, &UART_InitStructure);
   UART_ITConfig(UART1, UART_IT_RXIEN, ENABLE);

   NVIC_InitStructure.NVIC_IRQChannel = UART1_IRQn;
   NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init(&NVIC_InitStructure); 

   UART_Cmd(UART1, ENABLE);
}

03、编写MM32F013x UART1主机中断服务函数

MM32F0133C7P UART1主机中断服务函数,代码如下所示:

#define RX_MASTER_LEN   (3)
u8 g_Rx_Master_Buf[RX_MASTER_LEN] = {0x00};
u8 g_Rx_Master_Cnt = 0;
void UART1_IRQHandler(void)
{
     u8 res;
     if(UART_GetITStatus(UART1, UART_IT_RXIEN) != RESET) 
     {
          UART_ClearITPendingBit(UART1, UART_IT_RXIEN);
          res = UART_ReceiveData(UART1);
          g_Rx_Master_Buf[g_Rx_Master_Cnt] = res;
          if(g_Rx_Master_Cnt < RX_MASTER_LEN-1)
          {
             g_Rx_Master_Cnt++;
          }
          else
          {
             g_Rx_Master_Cnt = 0;
          }
     }
}

04、编写MM32F013x UART1从机中断服务函数

MM32F0133C7P UART1从机中断服务函数,代码如下所示:

#define RX_SLAVE_LEN    (3)
u8 g_Rx_Slave_Buf[RX_SLAVE_LEN] = {0x00};
u8 g_Rx_Slave_Cnt = 0;
void UART1_IRQHandler(void)
{
     u8 res;
     if(UART_GetITStatus(UART1, UART_IT_RXIEN) != RESET) 
     {
         UART_ClearITPendingBit(UART1, UART_IT_RXIEN);
         res = UART_ReceiveData(UART1);
         g_Rx_Slave_Buf[g_Rx_Slave_Cnt] = res;
         if(g_Rx_Slave_Cnt < RX_SLAVE_LEN-1)
         {
             g_Rx_Slave_Cnt++;
         }
         else
         {
             g_Rx_Slave_Cnt = 0;
         }  
     }
}

05、编写MM32F013x UART1主从机

通用发送数据函数

MM32F0133C7P UART1主从机通用发送函数,代码如下所示:

u8 g_Tx_Master_Buf[2] = {0xAA,0x55};
void bsp_UART_Send_Byte_Data(UART_TypeDef* uart,u8 data)
{
    UART_SendData(uart, data);
    while(!UART_GetFlagStatus(uart, UART_FLAG_TXEPT));
}
void bsp_UART_Send_Bytes_Data(UART_TypeDef* uart, u8* buf, u16 len)
{
    while(len--)
    {
        bsp_UART_Send_Byte_Data(uart,*buf++);
    }
}

06、编写MM32F013x UART1主机发送从机地址函数

MM32F0133C7P UART1主机发送从机地址函数,代码如下所示:

u8 g_Tx_Master_Buf[2] = {0xAA,0x55};
#define SLAVEADDR1       (0x01)
#define SLAVEADDR2       (0x02)
void bsp_UART_Send_SlaveAddr(UART_TypeDef* uart,u8 data)
{
    UART_SendData(uart, data);
    while(!UART_GetFlagStatus(uart, UART_FLAG_TXEPT));
}

07、编写MM32F013x UART1主机按键

发送从机地址和数据函数

宏定义按键GPIO端口和管脚,本实例只用到MM32F013x核心板的PA0作为KEY1对应核心板。

#define KEY1_GPIO_Port  GPIOA
#define KEY1_Pin         GPIO_Pin_0
#define KEY2_GPIO_Port  GPIOB
#define KEY2_Pin         GPIO_Pin_2
#define KEY3_GPIO_Port  GPIOB
#define KEY3_Pin        GPIO_Pin_10
#define KEY4_GPIO_Port  GPIOB
#define KEY4_Pin        GPIO_Pin_11
#define KEY1         GPIO_ReadInputDataBit(KEY1_GPIO_Port,KEY1_Pin)  //read key1
#define KEY2         GPIO_ReadInputDataBit(KEY2_GPIO_Port,KEY2_Pin)  //read key2
#define KEY3         GPIO_ReadInputDataBit(KEY3_GPIO_Port,KEY3_Pin)  //read key3
#define KEY4         GPIO_ReadInputDataBit(KEY4_GPIO_Port,KEY4_Pin)  //read key4
#define KEY1_DOWN_VALUE     1   //KEY1
#define KEY2_DOWN_VALUE     0   //KEY2
#define KEY3_DOWN_VALUE     0   //KEY3
#define KEY4_DOWN_VALUE     0   //KEY4
#define KEY1_PRES           1   //KEY1
#define KEY2_PRES           2   //KEY2
#define KEY3_PRES           3   //KEY3
#define KEY4_PRES           4   //KEY4
//Init Key GPIO
void bsp_Key_GPIO_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB ,ENABLE);

    GPIO_StructInit(&GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin  = KEY1_Pin;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
    GPIO_Init(KEY1_GPIO_Port, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin  = KEY2_Pin;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(KEY2_GPIO_Port, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin  = KEY3_Pin;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(KEY3_GPIO_Port, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin  = KEY4_Pin;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(KEY4_GPIO_Port, &GPIO_InitStructure);    
}

u8 bsp_Key_Scan(u8 mode)
{
    static u8 key_up = 1;
    if(mode)
    {
        key_up = 1;
    }
    if(key_up && ((KEY1 == KEY1_DOWN_VALUE) || (KEY2 == KEY2_DOWN_VALUE) || \
                  (KEY3 == KEY3_DOWN_VALUE) || (KEY4 == KEY4_DOWN_VALUE))) 
    {
        DELAY_Ms(10);

        key_up = 0;

        if(KEY1 == KEY1_DOWN_VALUE)
        {
            return KEY1_PRES;
        }
        else if(KEY2 == KEY2_DOWN_VALUE)
        {
            return KEY2_PRES;
        }
        else if(KEY3 == KEY3_DOWN_VALUE)
        {
            return KEY3_PRES;
        }
        else if(KEY4 == KEY4_DOWN_VALUE)
        {
            return KEY4_PRES;
        }
    }
    else if((KEY1 != KEY1_DOWN_VALUE) && (KEY3 != KEY3_DOWN_VALUE) && \
            (KEY4 != KEY4_DOWN_VALUE) && (KEY2 != KEY2_DOWN_VALUE))
    {
        key_up = 1;
    }

    return 0;
}

u8 Key_Nnum = 0;
void bsp_Process_Key_Task(void)
{
    static u8 Key_Value = 0;
    Key_Value = bsp_Key_Scan(0);
    switch(Key_Value)
    {
        case KEY1_PRES:           
           if(Key_Nnum == 0)
           {
                Key_Nnum = 1;
                bsp_UART_Send_SlaveAddr(UART1, SLAVEADDR1); //Send SlaveAddr1
                bsp_UART_Send_Bytes_Data(UART1, g_Tx_Master_Buf, sizeof(g_Tx_Master_Buf)); //Send data           
            }
            else if(Key_Nnum == 1)
            {
                Key_Nnum = 0;                
                bsp_UART_Send_SlaveAddr(UART1, SLAVEADDR2); //Send SlaveAddr2
                bsp_UART_Send_Bytes_Data(UART1, g_Tx_Master_Buf, sizeof(g_Tx_Master_Buf)); //Send data 
            }          
            break;
        case KEY2_PRES:
            break;
        case KEY3_PRES:
            break;
        case KEY4_PRES:
            break;
        default :
            break;        
    }
}

08、编写MM32F013x UART1主机

接收从机返回的数据函数

处理MM32F0133C7P UART1主机接收数据函数,代码如下所示:

 void bsp_UART_Master_Rec_Task(void)
{
  if(((g_Rx_Master_Buf[0] == SLAVEADDR1 ) || (g_Rx_Master_Buf[0] == SLAVEADDR2)) && (g_Rx_Master_Buf[1] == 0xAA) && (g_Rx_Master_Buf[2] == 0x55))
   {
      LED1_TOGGLE();   
      g_Rx_Master_Cnt = 0;
       memset(g_Rx_Master_Buf,0,sizeof(g_Rx_Master_Buf));
    }
}

09、编写MM32F013x UART1从机

接收主机发送的数据函数

处理MM32F0133C7P UART1主机接收数据函数,代码如下所示:

注意:g_Rx_Slave_Buf[1]为主机发送给从机的地址由从机接收判断,多从机通信需要修改从机地址宏:#define SLAVEADDR (0x02)等。

void bsp_UART_Slave_Rec_Task(void)
{
  if((g_Rx_Slave_Buf[0] == SLAVEADDR) && (g_Rx_Slave_Buf[1] == 0xAA) && (g_Rx_Slave_Buf[2] == 0x55))
  {
     LED1_TOGGLE();   
     bsp_UART_Send_Bytes_Data(UART1, g_Rx_Slave_Buf, sizeof(g_Rx_Slave_Buf));
     g_Rx_Slave_Cnt = 0;
     memset(g_Rx_Slave_Buf,0,sizeof(g_Rx_Slave_Buf));
  }
}

10、MM32F013x UART1 9bit多处理器通信功能演示

MM32F0133C7P多处理器通信功能演示:

主机main函数中调用DELAY_Init、LED_Init、bsp_Key_GPIO_Init和主机串口初始化函数bsp_UART1_Master_irq_9Bit_Init,在while(1)后台调用按键发送从机地址和发送数据函数bsp_Process_Key_Task以及处理接收从机返回数据函数bsp_UART_Master_Rec_Task代码如下所示:

s32 main(void)
{
    //SysTick init
    DELAY_Init();
    //LED Init
    LED_Init();
    //Key GPIO Init
    bsp_Key_GPIO_Init();
    //UART1 9Bit irt Init
    bsp_UART1_Master_irq_9Bit_Init(115200);
    while(1) 
    {
        //Key processing multi-processor communication
        bsp_Process_Key_Task();
        //Processing master receiving tasks
        bsp_UART_Master_Rec_Task();
    }
}

从机main函数中调用LED_Init和从机串口初始化函数bsp_UART1_Slave_irq_9Bit_Init,在while(1)后台调用处理从机接收任务函数bsp_UART_Slave_Rec_Task代码如下所示:

s32 main(void)
{
    //LED Init
    LED_Init();
    //UART1 9bit init
    bsp_UART1_Slave_irq_9Bit_Init(115200);
    while(1) 
    {
        //Processing slave receiving tasks
        bsp_UART_Slave_Rec_Task(); 
    }
}

分别编译以上主机和从机工程代码,然后烧录软件到MM32F0133C7P核心板上,烧录多从机时需修改从机工程代码的从机地址宏SLAVEADDR,编译后再烧录。本实例从机烧录0x01和x02为例作为演示,即1台主机和2台从机作为演示。

4、接线方式

MM32F0133C7P多处理器通信UART主机和从机接线方法:

各从机TX线与连接,RX线与连接,从机线与连接的TX接到主机RX端,从机线与连接的RX接到主机的TX端,主从机分别外接5.1~10K值范围之一的上拉电阻,本实例接5.1K上拉电阻。

MM32F0133C7P UART多处理器通信演示1台主机和2台从机分别发送和接收数据:

主机第1次按下MM32F0133C7P核心板上的S1按键,主机发送1字节从机地址0x01,接着发送2字节数据0xAA和0x55,从机1(地址0x01)在静默模式下自动比对主机寻址从机的地址0x01比对成功从机1被唤醒继续接收0xAA和0x55数据,收到完整的3字节数据时从机LED1状态翻转LED1亮并原样返回收到的数据给主机,此时从机2仍处于静默模式,主机完全收到从机1返回的3字节数据即0x01,0XAA,0x55时主机LED1状态翻转LED亮,实物现象如下图4所示。

图4(上从机1、中主机、下从机2)

主机第2次按下MM32F0133C7P核心板上的S1按键,主机发送1字节从机地址0x02,接着发送2字节数据0xAA和0x55,从机2(地址0x02)在静默模式下自动比对主机寻址从机的地址0x02比对成功从机2被唤醒继续接收0xAA和0x55数据,收到完整的3字节数据时从机LED1状态翻转LED1亮并原样返回收到的数据给主机,此时从机1仍处于静默模式其LED1维持上次点亮状态,主机完全收到从机2返回的3字节数据时即0x02,0XAA,0x55时主机LED1状态翻转LED灭,实物现象如下图5所示:

图5(上从机1、中主机、下从机2)

5、波形抓取

逻辑分析仪抓取到的MM32F0133C7多处理器通信波形图如下图6和图7所示:

图6上波形红色框注为主机发送:0x01、0xAA、0x55寻址从机1,从机(地址0x01)从静默模式唤醒并收到主机发送的数据0xAA和0x55时原样返回给主机如图6下波形蓝色框注:0x01、0xAA、0x55,此时从机2(地址0x02)并未作响应仍处于静默模式。

图6

图7上红色框注为主机发送:0x02、0xAA、0x55寻址从机2,从机(地址0x02)从静默模式唤醒并收到主机发送的数据0xAA和0x55时原样返回给主机如图7下波形蓝色框注:0x02、0xAA、0x55,此时从机1(地址0x01)并未作响应仍处于静默模式。

图7

转自:灵动MM32MCU

围观 162

本文对单片机通信性能的分析和评价方法进行研究,指出了物理接口电路分布参数的分析方法和保证通信系统通信接口控制性能固件正确性的组合选择法。对单片机通信性能评价时,可以使用本文提出单片机通信性能分析参数。这些参数是比特吞吐系数ξ、数据传输有效性σ和数据识别率η。利用这些参数,可以定量地对单片机通信性能进行分析,同时也可以利用这些参数进行单片机的选择和应用系统设计。

现代信息网络技术的一个突出特点,就是使工业控制系统6中的所有设备连接成网,从而在一个核心软件管理下工作(这个软件可能是分布式的操作系统,也可能是嵌入式操作系统),形成一个有机的整体。这种整体网络方式的现代工业控制系统具有传统独立控制系统所无法比拟的先进性,不仅能极大地提高工业设备的生产效率,还可以大大提高系统的安全性和可靠性。

目前,为了实现网络化系统,工业设备都必须以网络终端的形式出现在系统中,而这种网络终端大多用单片机或数字信号处理来实现。由于工业控制系统设备的多样性和分布性,智能模块方式的单片机终端已经成为主流设备控制方式。

随着信息和电子技术的发展,各种工业控制系统网络不断改进,这就对单片机通信功能的要求不断增加。特别是对各种现场总线技术中通信接口和通信协议,更是提出了新的通信要求:不仅能适应某一个通信协议,还希望能成为一种通信协议自动转换的智能终端。因此,单片机通信功能是否满足设计目标要求是必须设计中的一个关键问题。

在单片机应用技术中,需要有一个对单片机通信性能进行分析评价的理论方法,只有这样才能解决对单片机通信性能进行评价和设计的问题。本文的目的就是通过研究讨论,提出一个对单片机通信性能的分析和评价方法。 本文从单片机通信接口的物理结构和固件特性两个方面对单片机通信接口进行了分析,提出了接口电路物理性能分析模型和通信特性定量评价分析的参数。

一、串行通信口的物理特性

对单片机的通信性能可以从通信接口性能和软件处理能两个方面进行考虑。通信接口性能主要表现在与通信有关的电路物理性能上;而软件处理性能则与单片机的指令系统和CPU性能直接有关,所以,软件处理性能可以用单片机的固件特性来表示。

单片机串行通信接口一般分为两种,一种是同步串行通信接口(SPI),另一种是异步串行通信接口(SCI)。SPI具有串行通信速度高的特点,但一般需要 1条发送和1条接收串行数据通信线、1条通信目标选择线和1条同步时钟线,一共需要4条通信线(占用单片机的4个I/O引脚)。SOC虽然数据传输速度低于SPI,但一般只需要2条数据线和1条地线即可,也就是只需要3根通信线(占用单片机的3个引脚)。 SPI和SCI串行通信接口的基本电路结构如图1和图2所示。

单片机的通信性能分析与评价方法

单片机的通信性能分析与评价方法

从图中可以看到SPI和SCI的物理结构有很大差别:SPI的通信速率和信号接收正确率由时钟和接口物理特性决定;SCI的通信速率和信号接收正确率由物理接口和时钟分频率决定。

通信接口接收的是数字电平信号,因此,存在电平判别的问题。如果输入电路的物理特性对输入电平波形有影响,则会直接影响接收信号的正确性。因此,要求接收和发送电路的物理特性必须满足波形的要求。

通信息的物理特性还与通信介质和连接状态有关。图3是通信接口电路和驱动电路之间的待效电路图。

当数据传输速率远小于电路电压跟踪速度时,可认为每一位数据的电平保护足够长的时间。根据图3可以得到输出和输入信号的阶段响应: u=U(1-e -at) (1) 式中,u是数字信号高电平,a=1/[R(C1+C2)]是上升时间常数。图4是数字信号受到分布参数影响后的波形。 根据式(1)可知,在5V电源电压条件下,通信信号电平幅度上升到判别电压幅度(TTL高电平或CMOS高电平)所需时间是 T=-R(C1+C2)ln0.46(对TTL电路)或T=-R(C1+C2)ln0.72(对CMOS电路)。如果信号的波特率为fb,为确保正确接收,信号上升时间应当为信号脉冲宽度的1/4~1/10。 由此,当数字信号为TTL电平时,要求单片机接口电路的分布参数范围是

单片机的通信性能分析与评价方法

当数字系统为CMOS电平时,要求单片机接口电路的分布参数范围是
单片机的通信性能分析与评价方法

如果单片机的物理分布参数已经确定,则式(2)和式(3)就是最高通信速率的限制条件。 通过以上分析可以看出,单片机通信接口的物理特性对通信性能直接影响,主要反映在接口电路分布参数对数字信号波形的影响,进而引起接口电平判别失误。

二、单片机串行通信接口的固件特性

所谓单片机串行通信接口的固件特性,是指单片机串行通信接口的控制和支持硬件在串行通信时所具有技术特性。固件特性包括两个方面问题,一个方面是软件行为对硬件的要求条件,另一个是硬件电路所能提供的结构和功能特性。

1.单片机通信接口功能的控制方式

单片机串行通信接口功能的控制是在单片机内部硬件结构支持下的软件操作。单片机是面向寄存器的工作方式,因此,对于通信接口的控制是通过一系列的寄存器操作实现的。

基本控制步骤如下:

(1)设置必要参数(如通信速率、时钟源、终端方式等);

(2)设置数据结构(对于异步通信口);

(3)通过向发送寄存器写入数据,启动发送/接收——读取数据。 每一次通信(发送一个字节)都需要重复最后一个步骤。

由此可知,单片机串行通信接口寄存器的操作会直接影响通信接口的功能和性能。由于单片机的每一步骤操作都是执行1条指令,所以,单片机串行通信的真正发送时间,是向发送寄存器写数据指令结束的时刻。

单片机的通信性能分析与评价方法

2.单片机串行通信接口基本固件特性

单片机串行通信接口一般包括发送数据、接收数据、发送时钟、接收时钟、线路监测、碰撞处理、波特率设置、帧结构设备等。这些固件的特性有一个共同的特点,就是全部以寄存器为操作对象,并在每一个操作指令结束时执行寄存器操作,通过寄存器的输出电路实现相应的功能。由此可知,寄存器操作的特性,就是单片机串行通信接口固件的特性。

(1)次序固定的固件特性。
单片机串行以通信接口操作中,必须先进行相应的设置,才能实施通信。这种固定的次序是单片机串行通信接口的重要固件特性,如果忽略了这种次序特性,必然会导致通信失败。

(2)协议相关的固件特性。
通信协议是有效利用单片机串行通信接口的基本保证之一。如果在单片机的通信协议执行过程中出现问题,则通信功能就会丧失。

(3)隐含协调性。
所谓隐含协调性指隐含在通信指令集中的协议规定,如发送方与接收方的等待协议规定等。

由此,可以把单片机的固件特性用3个不同集合之交表示:设有通信接口的操作次序集合A、相关协议集合B和隐含规约集合C。A中的每一个元素都是一种正确的通信接口操作次序;B中每一个元素都是一种体现相关协议的通信接口操作要求;C中每一个元素都是一种隐含规约,则符合要求的通信接口控制固件必然是三者之交: Y=A∩B∩C

(4) 由此可知,要检查单片机串行通信接口的基本固件特性,可以使用式(2)进行判别;如果不能满足式(2),就表明单片机串行通信接口的固件特性有问题,会引起通信失效。

三、单片机通信性能分析

上述对单片机串行通信接口的物理特性和因件特性的分析,提供了单片机通信性能分析的基础。单片机通信性能分析包括比特吞吐特性分析、有效性分析和数据安全性分析。

1.比特吞吐特性分析

比特吞吐特性,是指单片机执行通信任务时单位时间内发送和接收的比特数目。比特吞吐特性不能用串行特性的波特率代替。比特吞特性不仅与波特率有关,更与单片机的固件特性有关。不同的通信协议会引起不同的通信操作,形成不同的操作固件。这种固件操作的有效性才是决定比特吞吐特性的关键。

在处理一组数据时,设通信协议处理数据的时间为tp,串行通信发送数据的时间为tc,则总的通信时间为t=tp+tc,因此,串行通信接口的比特吞吐特性可用如下函数表示: ξ=fctc/(tp+tc) (5) 式中,ξ叫做比特吞吐系数,fc是固件设备的串行通信波特率。可见,在fc固定的条件下,要提高比特吞吐特性,就必须尽量减少tp+tc并增加tc。在 tp=0这种极端情况下,比特吞吐系数才能等于通信波特率。 利用比特吞吐系数可以方便地检查单片机的串行通信能力能否满足应用系统的要求。例如,应用系统要求每秒钟内传输10个字节数据,相当于要求每秒钟的比特吞吐系数为80K。这里K是数据帧格式有效系数:异步串行通信中K>1;同步串行通信中K=1。

单片机的通信性能分析与评价方法

根据这个要求,可以对应用系统所设计的软件结构进行核实,如果不能满足,则说明应用系统不能满足对通信的要求,必须进行调整。

2.有效性分析

所谓有效性,是指对包括通信协议在内的整个通信过程的有效性。设单片机应用系统发送和接收的控制信息数据是随机函数y=P(x),其中x代表单位时间内的数据传输量。Y的数据期望是: σ=E[y]=E[P(x)] (6) σ叫做单片机串行通信系统的数据传输有效性系数。显然,在满足应用系统功能的前提下,σ的值小,说明数据传输的有效性高;反之,系统数据传输量大,说明系数控制信息的有效性差。必须注意,这里只考虑控制信息,并不包括必要的数据采集。

有效性分析就是要根据系数数据传输的随机分布,估计系统数据的有效性。可以直接利用有效性系数作为检验的标准。

此外,数据识别率也是衡量单片机通信效果和应用系统固件特性的一种重要参数。

数据识别率是指对接收到的数据语义理解的速度。设单片机接收到能代表完整意义的X个字节所需要的时间是tx,语义理解(翻译和判别)需要的时间为tY,则数据识别率为 η=X/(tx+ty) (7) 数据识别率表示了单位时间内单片机通信的效果,η值越大,表明单片机的整体固件特性越好,通信效率越高。

3.数据完全性

数据安全性不仅与系统的串行通信物理特征有关,更主要的是与应用系统通信的固件特性有关,尤其是通信协议中的应用层,直接关系系统的数据安全。

数据安全性可以用通信稳定性和数据识别率表示。 通信稳定性与通信线路和物理接口的侵入和干扰状态有关。对于单片机通信系统来说,当多个单片机采用串行连接的方法连接在1条总线上时,通信线路的侵入状态由通信协议直接确定。如使用令牌通信方式时,基本上没有侵入状态;但如果用客户/服务器方式,侵入状态将随线路上单片机数量的增加而恶化。这是比较复杂的通信系统行为特性分析问题,本文不再分析。

结论

本文对单片机通信接口的物理特性和固件特性进行了分析。指出了确定物理接口电路分布参数的分析方法,并导出了在不考虑传输线电感(PCB板)条件下电路分布参数与保证通信可靠条件之间的关系计算公式。这些计算表明,接口电路的分布参数是限制通信速度的主要因素之一。

通信接口控制的固件特性对单片机通信性能有重要影响。通信接口控制的固件特性需要用通信接口操作次序集合A、相关协议集合B和隐含规约集合C的交集进行检查。选择一组合适的固件结构组合,以保证通信系统通信接口控制性能固件的正确性。

对单片机通信性能评价时,可以使用本文提出的单片机通信性能分析参数。这些参数是比特吞吐系数ξ、数据传输有效性系数σ和数据识别率η。利用这些参数,可以定量地对单片机通信特性进行分析,同时也中以利用这些参数进行单片机的选择和应用系统设计。

必须指出,单片机通信系统的安全特性也是一个重要的应用基础,限于篇幅本文不再讨论。

转自:广电电器

围观 537

一、通信概述

按照数据传送方式分:

串行通信(一条数据线、适合远距离传输、控制较复杂)
并行通信(多条数据线、成本高、抗干扰性差)

按照通信的数据同步方式分:

异步通信(以1个字符为1帧、发送与接收时钟不一致)
同步通信(位同步、时钟一致)

按照数据的传输方向分:

单工(只能往一个方向传播)
半双工(数据传输可以沿两个方向,但是需要分时)
全双工(同时双向传输)

通信速率通常以比特率来表示,单位是:位/秒(bps),即每秒传输二进制代码的位数。之后会遇到一个波特率的概念,它表示每秒传输多少个码元。一般情况下,码元都是表示两种状态,即比特率=波特率。

二、串口通信

串口通信属于串行通信方式,它规定了接口的电气标准,没有规定接口插件电缆以及使用的协议。在此基础上用户可以建立自己的高层通信协议。

串口通信的接口标准有很多,有RS-232、RS-232C、RS-422A、RS-485等。比较常用的就是RS-232和RS-485。

RS-232有两种接口:25针(DB25、标准)、9针(DB9、非标准),其逻辑电平如下:

在TxD和RxD上:

逻辑1(MARK)=-3V~-15V
逻辑0(SPACE)=+3~+15V

在RTS、CTS、DSR、DTR和DCD等控制线上:

信号有效(接通,ON状态,正电压)=+3V~+15V
信号无效(断开,OFF状态,负电压)=-3V~-15V

当stm32与计算机串口通信时,需要用电平转换芯片MAX232,进行TTL电平和RS-232电平的转换。

RS-232的通信协议比较简单,通常遵循96-N-8-1格式。其是全双工的,且是异步通讯。 

stm32之通信

RS485没有规定或推荐任何数据协议,用户根据需要自己建立高层通信协议。 

区别于RS232, RS485的特性包括:
1. RS-485的电气特性:采用“2线制”,半双工通信,逻辑“1”以两线间的电压差为+(2—6) V表示;逻辑“0”以两线间的电压差为-(2—6)V表示。接口信号电平比RS -232-C降低了,就不易损坏接口电路的芯片,且该电平与TTL电平兼容,可方便与TTL 电路连接,其收发器芯片一般采用SP3485。

2. RS-485的数据最高传输速率为10Mbps

3. RS-485接口是采用平衡驱动器和差分接收器的组合,抗共模干能力增强,即抗噪声干扰性好。

4. RS-485接口的最大传输距离标准值为4000英尺,实际上可达 3000米,另外RS-232-C接口在总线上只允许连接1个收发器,即单站能力。而 RS-485接口在总线上是允许连接多达128个收发器。即具有多站能力,这样用户可以利用单一的RS-485接口方便地建立起设备网络。 因RS-485接口具有良好的抗噪声干扰性,长的传输距离和多站能力等上述优点就使其成为首选的串行接口。因为RS485接口组成的半双工网络 ,一般只需二根连线,所以RS485接口均采用屏蔽双绞线传输。 RS485接口连接器采用DB-9的9芯插头座,与智能终端RS485接口采用DB-9(孔) ,与键盘连接的键盘接口RS485采用DB-9(针)。

在stm32中,我们会接触到USART的概念,即通用同步异步收发器,同步和异步主要看其时钟是否需要对外提供。其能够满足外部设备对串行通信的要求,只不过其是TTL电平,需要进行电平转换。

注:stm32的奇偶校验位是算在数据位中的(8位-9位),与PC不同。
注:串口用于传输ASCII码字符,我们进行数据传送时,要转换为对应ASCII码的16进制数或字符串。
注:TXE是指弹仓满,TC是指枪膛满。

三、I2C通信

I2C是两线式串行总线,接口少、控制简单、通信速率较高。I2C总线只有两根双向信号线,一根是数据线SDA,另一根是时钟线SCL。

支持多主控多从控,不过同一时间点只能一个主控,连接节点数受地址限制。通过地址访问从控设备,通过仲裁决定主控设备优先级。因其采用时钟线,所以是同步传输。I2C还是半双工的。具体通信采用I2C的通信协议(寻址、起始/停止、应答等)。I2C用硬件实现起来较复杂,一般采用软件模拟I2C,移植方便。

stm32之通信

stm32之通信

四、CAN通信

CAN(Controller Area Network)是ISO国际标准化的串行通信协议。广泛应用于汽车、船舶等分布式控制系统。具有已经被大家认可的高性能和可靠性。CAN控制器通过组成总线的2根线(CAN-H和CAN-L)的电位差来确定总线的电平,在任一时刻,总线上有2种电平:显性电平和隐性电平。“显性”具有“优先”的意味,只要有一个单元输出显性电平,总线上即为显性电平,并且,“隐性”具有“包容”的意味,只有所有的单元都输出隐性电平,总线上才为隐性电平。(显性电平比隐性电平更强)。

总线上执行逻辑上的线“与”时,显性电平的逻辑值为“0”,隐性电平为“1”。

CAN总线是半双工的,虽然没有单独的时钟线,但是其采用位时序的方法进行同步传输。

CAN总线协议具有以下特点:

• 多主控制(ID仲裁)
• 系统的柔软性(没有地址信息)
• 通信速度快、距离远
• 具有错误检测、错误通知和错误恢复功能
• 故障封闭功能
• 连接节点多(理论上无限制,但是受总线时间延迟、电气负载影响,太多会降低速度)

CAN总线有两种标准如下图所示:

stm32之通信

CAN总线具有多节点可组网特性,如下图所示:
stm32之通信

从上面可以看出,CAN控制器(stm32芯片中带有)和CAN总线直接需要一个CAN收发器,可以采用TJA1040芯片。

CAN总线的工作原理

CAN总线使用串行数据传输方式,可以1Mb/s的速率在40m的双绞线上运行,也可以使用光缆连接,而且在这种总线上总线协议支持多主控制器。CAN与I2C总线的许多细节很类似,但也有一些明显的区别。当CAN总线上的一个节点(站)发送数据时,它以报文形式广播给网络中所有节点。对每个节点来说,无论数据是否是发给自己的,都对其进行接收。每组报文开头的11位字符为标识符,定义了报文的优先级,这种报文格式称为面向内容的编址方案。在同一系统中标识符是唯一的,不可能有两个站发送具有相同标识符的报文。当几个站同时竞争总线读取时,这种配置十分重要。当一个站要向其它站发送数据时,该站的CPU将要发送的数据和自己的标识符传送给本站的CAN芯片,并处于准备状态;当它收到总线分配时,转为发送报文状态。CAN芯片将数据根据协议组织成一定的报文格式发出,这时网上的其它站处于接收状态。每个处于接收状态的站对接收到的报文进行检测,判断这些报文是否是发给自己的,以确定是否接收它。由于CAN总线是一种面向内容的编址方案,因此很容易建立高水准的控制系统并灵活地进行配置。我们可以很容易地在CAN总线中加进一些新站而无需在硬件或软件上进行修改。当所提供的新站是纯数据接收设备时,数据传输协议不要求独立的部分有物理目的地址。它允许分布过程同步化,即总线上控制器需要测量数据时,可由网上获得,而无须每个控制器都有自己独立的传感器。

五、SPI通信

SPI 是Serial Peripheral Interface的缩写,直译为串行外围设备接口,SPI是Motorola公司推出的一种同步串行通讯方式,是一种四线同步总线,因其硬件功能很强,与SPI有关的软件就相当简单,使MCU有更多的时间处理其他事务。SPI内部结构简易图如下图所示:

stm32之通信

SPI接口一般使用4条线通信,分别如下:

• MISO:主设备输入/从设备输出
• MOSI:主设备输出/从设备输入
• SCLK:时钟信号线
• CS:从设备选择信号线

SPI一般用于一主多从,其结构示意图如下图所示:

stm32之通信

此外,SPI通信有4种不同的模式。下图是一种模式下的时序图:
stm32之通信

六、I2S通信

I2S是数字音频总线,在嵌入式音频系统设计中,并不是所有的MCU都支持I2S总线格式,再加上I2S还没有统一的接口标准,不同的厂家生产的设备接口也是五花八门,采用软件模拟实现I2S总线可有效解决在不支持其的MCU和设备之间通过I2S总线实现数据传输时出现的问题。

I2S为三线总线,3个信号分别为:

(1)串行时钟SCK,也叫位时钟(BCK)。即每发送1位数字音频数据,SCK上都有1个脉冲。SCK的频率=2×采样频率×采样位数。在数据传输过程中,I2S总线的发送器和接收器都可以作为系统的主机来提供系统的时钟频率。

(2)帧时钟WS,即命令(声道)选择,用于切换左右声道的数据。WS的频率等于采样频率,由系统主机提供。WS为“1”表示传输的是左声道的数据,WS为“0”表示传输的是右声道的数据。

(3)串行数据信号SD,用于传输二进制补码表示的音频数据。

I2S格式的信号无论有多少位有效数据,数据位的最高位(MSB)总是被最先传输,1次能够发送的数据决定于I2S格式的有效位数。

如下图所示为典型的时序图:

stm32之通信

七、USB通信

USB(Universal Serial Bus)是一种新的PC串行通信协议。是PC体系中的一套较新的工业标准,它支持单个主机与多个外设同时进行数据交换,大大满足了当今计算机外设追求高速度和高通用性的要求。

PC上的USB主机包括3个部分:USB主控制器/根Hub,USB系统软件和用户软件。下图是完整的USB系统组成。

stm32之通信

USB主机与设备之间的传输过程是这样的:在PC上,设备驱动程序通过调用USB驱动程序USBD,发出输入输出请求包IRP;这样,在USB驱动程序接到请求之后,调用主控制器驱动程序HCD,将IRP转化为USB的传输。当然,一个IRP可以包含一个或多个USB传输;接着,主控制器驱动程序将USB传输分解为总线事务,主控制器以包的形式发送给设备。  

USB设备类协议(USB DevICe Class Specification)与USB协议是互为补充的。针对USB的每一种设备类,都有一套特殊的设备类协议。正是USB采用了设备类的方式来对各种设备进行分类,才使USB总线能够有效的控制和管理各种设备,也使得各种设备的开发变的规范、简便。

此外,USB OTG既可以充当主机,也可以充当设备。

八、其他通信

比如无线通信、以太网通信。

转自: steed

围观 323

本文从对比两颗分立MCU与单芯片双核MCU开始(以LPC4350为例),展开介绍了非对称双核MCU的基础知识与重要特点。接下来,重点介绍了核间通信的概念与几种实现方式,尤其是基于消息池的控制/状态通信。然后,对内核互斥、初始化流程等一些重要的细节展开了论述。最后提出了双核任务分工的两种应用模型,并分别举例。

背景与基本概念

在开发MCU应用系统时,如果单颗MCU无法满足系统的要求,一个很普遍的做法就是使用两颗或更多的MCU,把一部分“杂项工作”分配给另一个有“助理”性质的低端MCU来完成。但是,采用两颗MCU,缺点也很明显,尤其是在芯片与PCB成本、系统可靠性及功耗方面都有先天的不足。此外,若采用了不同架构的MCU,还要面临需要不同的开发工具与开发人员的挑战。如果换一种思路,让MCU内部包含两个内核,其中一个用于主控,另一个用于协控,并且它们主控与协控在架构上能够向下兼容、高效通信,则在很多场合下都可以既保持多机系统的强大,又能避免多机系统的不足。

事实上,这即是“非对称多处理器(简称AMP)”架构的特点。AMP是与“对称多处理器(简称SMP)”相对的架构,后者各处理器有一致的编程模型,并且在分配工作时主要以均衡为原则。而AMP的优点在于精细的任务分工,灵活地适应不同情景,物尽其用,以最佳地平衡成本、性能与功耗。此外,AMP的编程难度也更低。因此,在MCU应用领域,AMP较SMP更为适合。

与独立的双MCU相比,AMP架构有很多优点。其中相当关键的就是,再添加一个内核的代价远比添加一个独立的MCU要低,尤其是当两个内核架构相似时,甚至仅相当于在现有硅片上再添加一两个UART。另一方面,两个内核可以有相同的主频,并且可以通过总线矩阵平等地访问片上资源。而在分立的双MCU方案中,协控MCU的主频常常远低于主控,并且双方使用低速的串行链路通信。

接下来,我们以恩智浦(NXP)半导体公司推出的LPC4300系列为例(尤以LPC4350型号为代表),对AMP MCU进行简单介绍。

非对称双核MCU的特点

AMP MCU一般用于相对大型的系统,这些系统对功能和性能都有较高的要求。在功能上,应支持较多的外设。LPC4350片载2个高速USB、2个CAN、工业以太网、图形LCD控制器,以及SDHC等接口;外加一些独有的逻辑可配置外设以及众多传统外设,适用于工控、能源、医疗、音频、车载、电机、监控等众多行业产品的开发。

性能的改善则是AMP MCU的灵魂。内核、存储器,以及总线架构对于性能有着至关重要的影响。图1展示了LPC4350的实现方式。

非对称双核MCU基础知识及核间通信
图1:LPC4350的内核、存储器以及总线连接图

首先是内核的选择。LPC4350基于32位的ARM Cortex-M4和Cortex-M0内核(以下简称M4和M0),两个内核均可在高达204MHz的主频下执行代码。其中,M4以信号处理和浮点运算能力见长,胜任很多原先要采用DSP才能满足的应用,并且继承了Cortex-M3的控制能力;另一方面,M0以其成本、能效和处理能力的压倒性优势,正迅速吸引开发人员从8/16位架构向上过渡。更重要的是,M4完全向下兼容M0,使用同一套开发工具即可开发、调试。

其次是存储器的容量和组织方式。LPC4350配备多达264KB片上RAM,并且这些RAM被划分成4组,每组连接一条单独的总线,而并非没有分块。如若不然,则会出现两个核竞争使用同一块RAM的情况——性能反而还不如只用单个内核!进一步,LPC4350还有两条总线连接到外部扩展的并行和串行存储器,故总共有6个独立的存储器地址空间——LPC4350无片上闪存。对于有片上闪存的型号,片上闪存也分为两块。

最后是总线架构。LPC4350内部有一个八层总线矩阵。它如同一组纵横开关,可以把CPU与包括存储器在内的众多从设备通过总线任意连接。合理分配总线接通关系,避免多个主设备(如CPU和DMA)同时访问相同的存储器或外设,可以最大地保证各条数据流并行不悖,从而可以充分发挥性能上的优势。

内核间通信

内核间的通信可分为两类:一类是控制与状态信息的通信,另一类则是数据通信。前者一般不携带数据,但往往有较高的实时要求;后者则主要是各类数据缓冲区,通常实时性要求偏低但数据量大。控制/状态通信有较大的通用性,并且与任务间的同步较为相似。这类通信适合由系统软件实现并提供编程接口。数据通信则往往与具体应用相关较大(尤其是在数据结构上),需要量体裁衣。在实现时,适合由应用软件定义各种数据结构。

内核间通过共享的RAM进行通信,并且每个内核都可以触发对方的一个中断源,通过准备数据-触发中断的方式进行通信,如图2所示。当然,内核也可以定期检查共享RAM的状态。

非对称双核MCU基础知识及核间通信
图2:内核间使用共享内存通信模式图

接下来,我们介绍基于消息队列和消息池的控制/状态通信方案。

消息队列:开设两个消息队列,一个用于M4发送消息给M0,另一个则是M0发送消息给M4。两个队列的地址需事先约定好。队列是循环队列,可以使用简单的数组配以读、写下标来实现,也可以使用链表结构来实现。前者实现简单、开销小,但消息只能是定长,不便于携带其它信息,还有,就是必须把数组放置在共享内存区连续的位置,灵活性低。基于链表的实现用指针链接每则消息,每则消息除了公共的链表控制部分外,还可以根据消息类别携带各种各样的附加参数,并且可以由系统软件的内存管理机制灵活分配消息内存,不过,缺点是相对复杂,额外开销大。若涉及动态内存管理,实时性将远不如基于数组的方案。

来源: 广电电器

围观 539

页面

订阅 RSS - 通信