查看: 5833|回复: 9

[原创] 【LPC54114Bonus任务】完成:54114双核与ESP8266的通讯

[复制链接]
  • TA的每日心情
    开心
    2017-12-26 12:04
  • 签到天数: 43 天

    连续签到: 1 天

    [LV.5]常住居民I

    4

    主题

    253

    帖子

    0

    高级会员

    Rank: 4

    积分
    620
    最后登录
    2018-7-6
    发表于 2017-8-13 18:52:37 | 显示全部楼层 |阅读模式
    本帖最后由 Y.fei 于 2017-8-14 09:32 编辑

      能申请到板板很高兴,感谢社区!
      原申请帖:https://www.nxpic.org.cn/module/forum/thread-611560-1-1.html

      通过学习社区里的帖子和NXP的例程,学习了54114双核的基本使用。完成了申请时设计的任务,实现了54114双核和ESP8266开发板的通讯,可以通过手机来控制LPC54114开发板上的LED。

    20170804_142718.jpg

    硬件线路:
      很简单,把ESP8266模块的串口连接到54114开发板的串口就好了。

    0.png

    系统结构:
      M4控制8个LED。
      M0+检测4个Key,使用了两个UART,一个Debug,一个连接ESP8266模块。
      M4和M0+之间通过MAILBOX通讯。
      M0+与ESP8266模块用AT命令通讯。


    实现的功能:
      1. M0+通过按键控制M4的8个LED流水灯的状态。
      2. M0+通过按键控制ESP8266模块上的RGB灯的状态。
      3. M4在系统上电后分别发送命令到M0+来初始化ESP8266模块,使ESP8266连接到WiFi,并打开TCP服务器模式。
      4. 使用PC或手机通WiFi网络连接到8266的TCP服务器,发送命令来控制54114开发板上的LED。

    实现步骤:
    1. 双核MAILBOX通讯
            参照NXP官方的双核例程,M4通过定时器定时把参数BitNum的地址发送到M0,M0通过中断接收到数据后改变参数BitNum的值后再发回M4,M4中断接收到信号后,根据BitNum的值改变LED的状态。
    M4部分代码:

    1. while (1)
    2. {
    3.         if(M0plus_Trigger)
    4.         {
    5.                 M0plus_Trigger = 0;
    6.                 MAILBOX_mutexWait();
    7.                 LPC_MBOX->BOX[0].IRQ = (uint32_t)&BitNum;        // 发送BitNum地址到M0
    8.                 MAILBOX_mutexRelease();
    9.         }
    10. }
    复制代码
    1. /*----------------------------------------------------------------------------
    2.   MAILBOX_IRQHandler
    3. *----------------------------------------------------------------------------*/
    4. void MAILBOX_IRQHandler(void)
    5. {
    6.         LPC_MBOX->BOX[1].IRQCLR = 0xFFFFFFFF;       /* clear own mailbox            */
    7.         if (BitNum >= LED_GetCount())
    8.         {
    9.                 BitNum = 0;
    10.         }
    11.         LED_SetOut(1 << BitNum);                        // 输出新的LED的状态
    12. }
    复制代码
    M0部分代码:
    1. void MAILBOX_IRQHandler(void)
    2. {
    3.         uint32_t bit;
    4.         uint32_t *pbit;
    5.         pbit = (uint32_t *)LPC_MBOX->BOX[0].IRQ;        // 获取BitNum的地址
    6.         MAILBOX_mutexWait();
    7.         bit = *pbit;                // 获取BitNum的值
    8.         bit ++;
    9.         *pbit = bit;                // 新值写回BitNum
    10.         MAILBOX_mutexRelease();
    11.         LPC_MBOX->BOX[0].IRQCLR = 0xFFFFFFFF;        // clear own mailbox
    12.         LPC_MBOX->BOX[1].IRQSET = 1;        // signal change to M4
    13. }
    复制代码

        上边是官方例程中的代码,实现的是流水灯的功能。双核之间只传递了一个参数BitNum的地址。
        我在此基础上实现了双向数据的传输,M4向M0发送的数据分两种类型,一种同上一样是BitNum的地址,另一种为控制ESP8266的命令。M0同样也发送命令到M4,分3种类型,1.进入LED单独控制模式,控制一个LED的状态;2.控制流水灯速度;3.进入流水灯模式,可控制流水灯方向。
    M4部分代码:

    1. //---------------------------------------------------------------------------- MAILBOX_IRQHandler
    2. void MAILBOX_IRQHandler(void)
    3. {
    4.         uint32_t buf;
    5.         buf = LPC_MBOX->BOX[1].IRQ;        // 获取M0发送的数据
    6.         MAILBOX_mutexWait();
    7.         if(buf & SP_COMM_FLAG)                // 判断是否LED速度改变命令
    8.         {
    9.                 LedMode = 0;
    10.                 ticks_t = buf & 0xff;        // 更改定时器的值
    11.         }
    12.         else if(buf & LED_ON_COMM)        // 判断是否单独打开LED命令
    13.         {
    14.                 if(LedMode == 0)
    15.                 {
    16.                         LED_SetOut(0);
    17.                         LedMode = 1;
    18.                 }
    19.                 LED_On(buf & 0x0f);        // 改变一个LED状态
    20.         }
    21.         else if(buf & LED_OFF_COMM)        // 判断是否单独关闭LED命令
    22.         {
    23.                 if(LedMode == 0)
    24.                 {
    25.                         LED_SetOut(0);
    26.                         LedMode = 1;
    27.                 }
    28.                 LED_Off(buf & 0x0f);        // 改变一个LED状态
    29.         }
    30.         else if(buf & LED_ZZ_COMM)        // 判断是否流水灯命令
    31.         {
    32.                 LedMode = 0;                // 进入流水灯模式
    33.         }
    34.         else if(LedMode == 0)
    35.         {
    36.                 if ((int32_t)BitNum < 0)
    37.                 {
    38.                         BitNum = LED_GetCount() - 1;
    39.                 }
    40.                 if (BitNum >= LED_GetCount())
    41.                 {
    42.                         BitNum = 0;
    43.                 }
    44.                 LED_SetOut(1 << BitNum);// 输出新的LED的状态
    45.         }
    46.         MAILBOX_mutexRelease();
    47.         LPC_MBOX->BOX[1].IRQCLR = 0xFFFFFFFF;                // clear own mailbox
    48. }

    49. void MAILBOX_Send(uint32_t dat)
    50. {
    51.         MAILBOX_mutexWait();
    52.         LPC_MBOX->BOX[0].IRQ = dat;
    53.         MAILBOX_mutexRelease();
    54. }
    55. //---------------------------------------------------------------------------- Main Program
    56. int main(void)
    57. {
    58.         volatile uint32_t stopHereForM0plusDebugging = 0;
    59.         SystemCoreClockUpdate();
    60.         LED_Initialize();
    61.         MAILBOX_Initialize();                                // 初始化mailbox (M4 only)
    62.         SysTick_Config(SystemCoreClock/100);                // 定时器初始化
    63.         // 启动M0+ core, Setup M0+ stack pointer and  reset vector ( from M0+ flash image)
    64.         Chip_CPU_CM0Boot((uint32_t *)(*(uint32_t *)(M0plus_IMAGE_START + 4)),
    65.                                 (uint32_t *)(*(uint32_t *)(M0plus_IMAGE_START + 0)) );
    66.         stopHereForM0plusDebugging = 1;
    67.         
    68.         LED_SetOut(255);        Delay1s();                //延时等待ESP8266启动
    69.         LED_SetOut(0);                Delay1s();
    70.         LED_SetOut(255);        Delay1s();
    71.         
    72.         MAILBOX_Send(AT_COMM_FLAG | AT_COMM1);                //发送ESP8266命令1
    73.         
    74.         LED_SetOut(0);                Delay1s();                //延时1s
    75.         
    76.         MAILBOX_Send(AT_COMM_FLAG | AT_COMM2);                //发送ESP8266命令2
    77.         
    78.         LED_SetOut(255);        Delay1s();                //延时1s
    79.         
    80.         MAILBOX_Send(AT_COMM_FLAG | AT_COMM3);                //发送ESP8266命令3 启动TCP服务器
    81.         
    82.         LED_SetOut(0);                Delay1s();                //延时1s
    83.         LED_SetOut(255);
    84.         
    85.         NVIC_SetPriority (MAILBOX_IRQn, 1);
    86.         NVIC_EnableIRQ(MAILBOX_IRQn);                        // 打开mailbox中断
    87.         
    88.         while (1)
    89.         {
    90.                 if((M0plus_Trigger) && (LedMode == 0))
    91.                 {
    92.                         M0plus_Trigger = 0;
    93.                         MAILBOX_Send((uint32_t)&BitNum);        // 发送BitNum地址到M0
    94.                 }
    95.         }
    96. }
    97. //----------------------------------------------------------------------------
    复制代码
    M0部分代码:
    1. //---------------------------------------------------------------------------- MAILBOX_IRQHandler
    2. void MAILBOX_IRQHandler(void)
    3. {
    4.         uint32_t buf;
    5.         uint32_t bit;
    6.         uint32_t *pbit;
    7.         buf = LPC_MBOX->BOX[0].IRQ;        // 获取M4发送的数据
    8.         MAILBOX_mutexWait();
    9.         if(buf & AT_COMM_FLAG)                // 判断数据是否为ESP8266命令
    10.         {
    11.                 AT_Send(buf);
    12.         }
    13.         else
    14.         {
    15.                 pbit = (uint32_t *)buf;        // 获取BitNum的地址
    16.                 bit = *pbit;                // 获取BitNum的值
    17.                
    18.                 if(LedMode == 0)        bit ++;        //流水灯正转
    19.                 else                        bit --;        //流水灯反转
    20.         
    21.                 *pbit = bit;                // 新值写回BitNum
    22.         }
    23.         MAILBOX_mutexRelease();
    24.         LPC_MBOX->BOX[0].IRQCLR = 0xFFFFFFFF;        // clear own mailbox
    25.         LPC_MBOX->BOX[1].IRQSET = 1;        // signal change to M4
    26.         MAILBOX_mutexRelease();
    27. }
    28. //---------------------------------------------------------------------------- Main Program
    29. int main(void)
    30. {
    31.         uint32_t comm;
    32.         uint32_t key;
    33.         SystemCoreClockUpdate();
    34.         Buttons_Initialize();
    35.         Usart_Init();
    36.         NVIC_EnableIRQ(MAILBOX_IRQn);                //打开mailbox中断
    37.         Log_printf(start_up);
    38.         while (1)
    39.         {
    40.                 comm = AT_Receive();                //接收并分析ESP8266命令
    41.                 if(comm)
    42.                 {
    43.                         MAILBOX_Send(comm);
    44.                 }
    45.                
    46.                 key = Buttons_GetState();        //检测按键
    47.                 while(Buttons_GetState());
    48.                 if(key & BUTTON0)                //按键0改变流水灯方向
    49.                 {
    50.                         if(LedMode)        LedMode = 0;
    51.                         else                LedMode = 1;
    52.                         MAILBOX_Send(LED_ZZ_COMM);
    53.                 }
    54.                 if(key & BUTTON1)                //按键1加快流水灯速度
    55.                 {
    56.                         if(speed < 50) speed ++;
    57.                         MAILBOX_Send(SP_COMM_FLAG | speed);
    58.                 }
    59.                 if(key & BUTTON2)                //按键2减慢流水灯方向
    60.                 {
    61.                         if(speed > 0) speed --;
    62.                         MAILBOX_Send(SP_COMM_FLAG | speed);
    63.                 }
    64.                 if((key & BUTTON3) || RGBflag)        //按键3改变8266板上RGB灯状态
    65.                 {
    66.                         RGBflag = 0;
    67.                         
    68.                         RGBMode++;
    69.                         if(RGBMode == 1)        AT_Send(AT_COMM_R_ON);
    70.                         else if(RGBMode == 2)        AT_Send(AT_COMM_R_OFF);
    71.                         else if(RGBMode == 3)        AT_Send(AT_COMM_G_ON);
    72.                         else if(RGBMode == 4)        AT_Send(AT_COMM_G_OFF);
    73.                         else if(RGBMode == 5)        AT_Send(AT_COMM_B_ON);
    74.                         else if(RGBMode == 6)        AT_Send(AT_COMM_B_OFF);
    75.                         else RGBMode = 0;
    76.                 }
    77.                
    78.                 if(key) Log_printf("\r\nLedMode = %d        Speed = %d", LedMode, speed);
    79.                 key = 0;
    80.         }
    81. }
    82. //---------------------------------------------------------------------------- End
    复制代码

    2.与ESP8266的通讯
      发送数据到ESP8266时,由M4分别发送命令给M0,M0再把收到的命令分别转换成AT指令,通过UART发送给ESP8266;接收数据时,M0把接收到的8266的数据根据通讯协议,解析成各种指令,再发送给M4,由M4来执行指令。
    发送AT命令:

    1. const char * AT_COMM1_STR = "AT+CIPMUX=1\r\n";
    2. const char * AT_COMM2_STR = "AT+LANSTART\r\n";
    3. const char * AT_COMM3_STR = "AT+CIPSERVER=1,5000\r\n";
    4. const char * AT_COMM_R_ON_STR  = "AT+CIOWRITE=15,1\r\n";        // RGB红灯亮
    5. const char * AT_COMM_R_OFF_STR = "AT+CIOWRITE=15,0\r\n";        // RGB红灯灭
    6. const char * AT_COMM_G_ON_STR  = "AT+CIOWRITE=12,1\r\n";        // RGB绿灯亮
    7. const char * AT_COMM_G_OFF_STR = "AT+CIOWRITE=12,0\r\n";        // RGB绿灯灭
    8. const char * AT_COMM_B_ON_STR  = "AT+CIOWRITE=13,1\r\n";        // RGB蓝灯亮
    9. const char * AT_COMM_B_OFF_STR = "AT+CIOWRITE=13,0\r\n";        // RGB蓝灯灭

    10. void AT_Send(int32_t comm)
    11. {
    12.         switch(comm & 0x0f)
    13.         {
    14.                 case AT_COMM1:                Driver_USART5.Send(AT_COMM1_STR,        strlen(AT_COMM1_STR));                break;
    15.                 case AT_COMM2:                Driver_USART5.Send(AT_COMM2_STR,        strlen(AT_COMM2_STR));                break;
    16.                 case AT_COMM3:                Driver_USART5.Send(AT_COMM3_STR,        strlen(AT_COMM3_STR));                break;
    17.                 case AT_COMM_R_ON:        Driver_USART5.Send(AT_COMM_R_ON_STR,        strlen(AT_COMM_R_ON_STR));        break;
    18.                 case AT_COMM_R_OFF:        Driver_USART5.Send(AT_COMM_R_OFF_STR,        strlen(AT_COMM_R_OFF_STR));        break;
    19.                 case AT_COMM_G_ON:        Driver_USART5.Send(AT_COMM_G_ON_STR,        strlen(AT_COMM_G_ON_STR));        break;
    20.                 case AT_COMM_G_OFF:        Driver_USART5.Send(AT_COMM_G_OFF_STR,        strlen(AT_COMM_G_OFF_STR));        break;
    21.                 case AT_COMM_B_ON:        Driver_USART5.Send(AT_COMM_B_ON_STR,        strlen(AT_COMM_B_ON_STR));        break;
    22.                 case AT_COMM_B_OFF:        Driver_USART5.Send(AT_COMM_B_OFF_STR,        strlen(AT_COMM_B_OFF_STR));        break;
    23.         }
    24. }
    复制代码
    接收解析8266数据:
    1. int32_t AT_Receive(void)
    2. {
    3.         static char buf[8];
    4.         static char i = 0;
    5.         static char t;
    6.         int32_t ret=USART5_Receive(&t, 1);
    7.         if(ret != 0) return 0;
    8.         buf[i] = t;
    9.         ret = 0;
    10.         if(buf[0] == '[')
    11.         {
    12.                 if(buf[i] == ']')
    13.                 {
    14.                         if(buf[1] == 'K')
    15.                         {
    16.                                 if((buf[2] >= '0') && (buf[2] <= '7'))
    17.                                 {
    18.                                         ret = LED_ON_COMM | (buf[2] & 0x0F);
    19.                                 }
    20.                         }
    21.                         else if(buf[1] == 'G')
    22.                         {
    23.                                 if((buf[2] >= '0') && (buf[2] <= '7'))
    24.                                 {
    25.                                         ret = LED_OFF_COMM | (buf[2] & 0x0F);
    26.                                 }
    27.                         }
    28.                         else if(buf[1] == '+')
    29.                         {
    30.                                 LedMode = 0;
    31.                                 ret = LED_ZZ_COMM;
    32.                         }
    33.                         else if(buf[1] == '-')
    34.                         {
    35.                                 LedMode = 1;
    36.                                 ret = LED_ZZ_COMM;
    37.                         }
    38.                         else if((buf[1] == 'S') && (buf[2] == '+'))
    39.                         {
    40.                                 if(speed >  0) speed --;
    41.                                 ret = SP_COMM_FLAG | speed;
    42.                         }
    43.                         else if((buf[1] == 'S') && (buf[2] == '-'))
    44.                         {
    45.                                 if(speed < 50) speed ++;
    46.                                 ret = SP_COMM_FLAG | speed;
    47.                         }
    48.                         else if(buf[1] == 'R')
    49.                         {
    50.                                 RGBflag = 1;
    51.                         }
    52.                         
    53.                         i = 0;
    54.                         buf[0] = 0;
    55.                 }
    56.                 else
    57.                 {
    58.                         i++;
    59.                         if(i > 6)
    60.                         {
    61.                                 i = 0;
    62.                                 buf[0] = 0;
    63.                         }
    64.                 }
    65.         }
    66.         return ret;
    67. }
    复制代码

    3. PC/手机到54114的通讯协议
      PC/手机连接到ESP8266的TCP服务器后,可以发送命令来控制LED。
      这里用了一个很简单的通讯协议。
      使用方括号'['和']'分别表示命令的起始和结束,中间用一个或两个字符表示命令,支持以下几种命令:
                          [Kx]:x为0-7,分别表示点亮0-7号LED。
                          [Gx]:x为0-7,分别表示关闭0-7号LED。
                          [+]:流水灯正转。
                          [-]:流水灯反转。
                          [S+]:流水灯加速。
                          [S-]:流水灯减速。
                          [R]:控制RGB灯。

    演示:
      动图有点大,请耐心等待图片加载。。。
    K-ZF.gif
      按键Key0:切换流水灯方向。

    K-S .gif
      连续按Key1减缓流水灯速度,连续按Key2加快流水灯速度。

    K-RGB.gif
      按Key3,依次点亮关闭ESP8266板上RGB灯的红绿蓝状态。

    S70813-175414.jpg
      在手机上使用网络调试助手连接ESP8266,TCP客户端模式连接ESP8266的IP端口。

    T-RGB.gif
      发送命令[R]控制RGB灯,效果和按键Key3相同。

    T-KG.gif
      手机控制54114开发板LED演示。依次发送以下命令:

        [K1]:进入LED单独控制模式,点亮LED1。
        [K5]:点亮LED5。
        [G5]:关闭LED5。
        [S+]:进入流水灯模式,流水灯正转。

    该会员没有填写今日想说内容.
    回复

    使用道具 举报

  • TA的每日心情

    2018-2-28 16:09
  • 签到天数: 65 天

    连续签到: 1 天

    [LV.6]常住居民II

    8

    主题

    238

    帖子

    0

    中级会员

    Rank: 3Rank: 3

    积分
    488
    最后登录
    2019-9-18
    发表于 2017-8-14 09:24:13 | 显示全部楼层
    厉害了!!!
    回复

    使用道具 举报

  • TA的每日心情

    2018-2-28 16:09
  • 签到天数: 65 天

    连续签到: 1 天

    [LV.6]常住居民II

    8

    主题

    238

    帖子

    0

    中级会员

    Rank: 3Rank: 3

    积分
    488
    最后登录
    2019-9-18
    发表于 2017-8-14 09:24:44 | 显示全部楼层
    8266用的很溜!!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2019-2-11 11:14
  • 签到天数: 345 天

    连续签到: 1 天

    [LV.8]以坛为家I

    18

    主题

    1317

    帖子

    4

    金牌会员

    Rank: 6Rank: 6

    积分
    3268
    最后登录
    2023-3-16
    发表于 2017-8-14 16:43:56 | 显示全部楼层
    向你学习!!
    回复

    使用道具 举报

    该用户从未签到

    0

    主题

    1

    帖子

    0

    新手上路

    Rank: 1

    积分
    44
    最后登录
    2017-9-6
    发表于 2017-8-18 09:02:58 | 显示全部楼层
    想请教一下前辈,双核之间通过中断实现数据传输,这样双核的优势突出在什么地方啊,与外部两个MCU通过串口相连接相比。
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    0

    主题

    47

    帖子

    0

    中级会员

    Rank: 3Rank: 3

    积分
    415
    最后登录
    2018-12-5
    发表于 2017-8-29 16:58:57 | 显示全部楼层
    手机APP给力啊 自己做的吗
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2017-12-26 12:04
  • 签到天数: 43 天

    连续签到: 1 天

    [LV.5]常住居民I

    4

    主题

    253

    帖子

    0

    高级会员

    Rank: 4

    积分
    620
    最后登录
    2018-7-6
     楼主| 发表于 2017-8-30 11:29:12 | 显示全部楼层
    guiyi 发表于 2017-8-29 16:58
    手机APP给力啊 自己做的吗

    网上下的,网络调试助手
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    昨天 17:56
  • 签到天数: 874 天

    连续签到: 1 天

    [LV.10]以坛为家III

    3

    主题

    1534

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    4801
    最后登录
    2025-7-23
    发表于 2017-8-30 12:48:18 | 显示全部楼层
    你这个厉害!
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    0

    主题

    47

    帖子

    0

    中级会员

    Rank: 3Rank: 3

    积分
    415
    最后登录
    2018-12-5
    发表于 2017-8-30 13:25:36 | 显示全部楼层
    Y.fei 发表于 2017-8-30 11:29
    网上下的,网络调试助手

    哦~厉害了 居然有手机端的
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    擦汗
    2021-7-5 15:45
  • 签到天数: 664 天

    连续签到: 1 天

    [LV.9]以坛为家II

    42

    主题

    1594

    帖子

    19

    金牌会员

    Rank: 6Rank: 6

    积分
    5618
    最后登录
    2021-12-22
    发表于 2017-10-23 18:57:00 | 显示全部楼层
    不错,哪天用我的小e学学....
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2025-7-24 05:32 , Processed in 0.109046 second(s), 29 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表