在线时间26 小时
UID3323770
注册时间2016-11-9
NXP金币0
TA的每日心情 | 开心 2017-12-26 12:04 |
---|
签到天数: 43 天 连续签到: 1 天 [LV.5]常住居民I
高级会员

- 积分
- 620
- 最后登录
- 2018-7-6
|
本帖最后由 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。
硬件线路:
很简单,把ESP8266模块的串口连接到54114开发板的串口就好了。
系统结构:
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部分代码:
- while (1)
- {
- if(M0plus_Trigger)
- {
- M0plus_Trigger = 0;
- MAILBOX_mutexWait();
- LPC_MBOX->BOX[0].IRQ = (uint32_t)&BitNum; // 发送BitNum地址到M0
- MAILBOX_mutexRelease();
- }
- }
复制代码- /*----------------------------------------------------------------------------
- MAILBOX_IRQHandler
- *----------------------------------------------------------------------------*/
- void MAILBOX_IRQHandler(void)
- {
- LPC_MBOX->BOX[1].IRQCLR = 0xFFFFFFFF; /* clear own mailbox */
- if (BitNum >= LED_GetCount())
- {
- BitNum = 0;
- }
- LED_SetOut(1 << BitNum); // 输出新的LED的状态
- }
复制代码 M0部分代码:
- void MAILBOX_IRQHandler(void)
- {
- uint32_t bit;
- uint32_t *pbit;
- pbit = (uint32_t *)LPC_MBOX->BOX[0].IRQ; // 获取BitNum的地址
- MAILBOX_mutexWait();
- bit = *pbit; // 获取BitNum的值
- bit ++;
- *pbit = bit; // 新值写回BitNum
- MAILBOX_mutexRelease();
- LPC_MBOX->BOX[0].IRQCLR = 0xFFFFFFFF; // clear own mailbox
- LPC_MBOX->BOX[1].IRQSET = 1; // signal change to M4
- }
复制代码
上边是官方例程中的代码,实现的是流水灯的功能。双核之间只传递了一个参数BitNum的地址。
我在此基础上实现了双向数据的传输,M4向M0发送的数据分两种类型,一种同上一样是BitNum的地址,另一种为控制ESP8266的命令。M0同样也发送命令到M4,分3种类型,1.进入LED单独控制模式,控制一个LED的状态;2.控制流水灯速度;3.进入流水灯模式,可控制流水灯方向。
M4部分代码:
- //---------------------------------------------------------------------------- MAILBOX_IRQHandler
- void MAILBOX_IRQHandler(void)
- {
- uint32_t buf;
- buf = LPC_MBOX->BOX[1].IRQ; // 获取M0发送的数据
- MAILBOX_mutexWait();
- if(buf & SP_COMM_FLAG) // 判断是否LED速度改变命令
- {
- LedMode = 0;
- ticks_t = buf & 0xff; // 更改定时器的值
- }
- else if(buf & LED_ON_COMM) // 判断是否单独打开LED命令
- {
- if(LedMode == 0)
- {
- LED_SetOut(0);
- LedMode = 1;
- }
- LED_On(buf & 0x0f); // 改变一个LED状态
- }
- else if(buf & LED_OFF_COMM) // 判断是否单独关闭LED命令
- {
- if(LedMode == 0)
- {
- LED_SetOut(0);
- LedMode = 1;
- }
- LED_Off(buf & 0x0f); // 改变一个LED状态
- }
- else if(buf & LED_ZZ_COMM) // 判断是否流水灯命令
- {
- LedMode = 0; // 进入流水灯模式
- }
- else if(LedMode == 0)
- {
- if ((int32_t)BitNum < 0)
- {
- BitNum = LED_GetCount() - 1;
- }
- if (BitNum >= LED_GetCount())
- {
- BitNum = 0;
- }
- LED_SetOut(1 << BitNum);// 输出新的LED的状态
- }
- MAILBOX_mutexRelease();
- LPC_MBOX->BOX[1].IRQCLR = 0xFFFFFFFF; // clear own mailbox
- }
- void MAILBOX_Send(uint32_t dat)
- {
- MAILBOX_mutexWait();
- LPC_MBOX->BOX[0].IRQ = dat;
- MAILBOX_mutexRelease();
- }
- //---------------------------------------------------------------------------- Main Program
- int main(void)
- {
- volatile uint32_t stopHereForM0plusDebugging = 0;
- SystemCoreClockUpdate();
- LED_Initialize();
- MAILBOX_Initialize(); // 初始化mailbox (M4 only)
- SysTick_Config(SystemCoreClock/100); // 定时器初始化
- // 启动M0+ core, Setup M0+ stack pointer and reset vector ( from M0+ flash image)
- Chip_CPU_CM0Boot((uint32_t *)(*(uint32_t *)(M0plus_IMAGE_START + 4)),
- (uint32_t *)(*(uint32_t *)(M0plus_IMAGE_START + 0)) );
- stopHereForM0plusDebugging = 1;
-
- LED_SetOut(255); Delay1s(); //延时等待ESP8266启动
- LED_SetOut(0); Delay1s();
- LED_SetOut(255); Delay1s();
-
- MAILBOX_Send(AT_COMM_FLAG | AT_COMM1); //发送ESP8266命令1
-
- LED_SetOut(0); Delay1s(); //延时1s
-
- MAILBOX_Send(AT_COMM_FLAG | AT_COMM2); //发送ESP8266命令2
-
- LED_SetOut(255); Delay1s(); //延时1s
-
- MAILBOX_Send(AT_COMM_FLAG | AT_COMM3); //发送ESP8266命令3 启动TCP服务器
-
- LED_SetOut(0); Delay1s(); //延时1s
- LED_SetOut(255);
-
- NVIC_SetPriority (MAILBOX_IRQn, 1);
- NVIC_EnableIRQ(MAILBOX_IRQn); // 打开mailbox中断
-
- while (1)
- {
- if((M0plus_Trigger) && (LedMode == 0))
- {
- M0plus_Trigger = 0;
- MAILBOX_Send((uint32_t)&BitNum); // 发送BitNum地址到M0
- }
- }
- }
- //----------------------------------------------------------------------------
复制代码 M0部分代码:
- //---------------------------------------------------------------------------- MAILBOX_IRQHandler
- void MAILBOX_IRQHandler(void)
- {
- uint32_t buf;
- uint32_t bit;
- uint32_t *pbit;
- buf = LPC_MBOX->BOX[0].IRQ; // 获取M4发送的数据
- MAILBOX_mutexWait();
- if(buf & AT_COMM_FLAG) // 判断数据是否为ESP8266命令
- {
- AT_Send(buf);
- }
- else
- {
- pbit = (uint32_t *)buf; // 获取BitNum的地址
- bit = *pbit; // 获取BitNum的值
-
- if(LedMode == 0) bit ++; //流水灯正转
- else bit --; //流水灯反转
-
- *pbit = bit; // 新值写回BitNum
- }
- MAILBOX_mutexRelease();
- LPC_MBOX->BOX[0].IRQCLR = 0xFFFFFFFF; // clear own mailbox
- LPC_MBOX->BOX[1].IRQSET = 1; // signal change to M4
- MAILBOX_mutexRelease();
- }
- //---------------------------------------------------------------------------- Main Program
- int main(void)
- {
- uint32_t comm;
- uint32_t key;
- SystemCoreClockUpdate();
- Buttons_Initialize();
- Usart_Init();
- NVIC_EnableIRQ(MAILBOX_IRQn); //打开mailbox中断
- Log_printf(start_up);
- while (1)
- {
- comm = AT_Receive(); //接收并分析ESP8266命令
- if(comm)
- {
- MAILBOX_Send(comm);
- }
-
- key = Buttons_GetState(); //检测按键
- while(Buttons_GetState());
- if(key & BUTTON0) //按键0改变流水灯方向
- {
- if(LedMode) LedMode = 0;
- else LedMode = 1;
- MAILBOX_Send(LED_ZZ_COMM);
- }
- if(key & BUTTON1) //按键1加快流水灯速度
- {
- if(speed < 50) speed ++;
- MAILBOX_Send(SP_COMM_FLAG | speed);
- }
- if(key & BUTTON2) //按键2减慢流水灯方向
- {
- if(speed > 0) speed --;
- MAILBOX_Send(SP_COMM_FLAG | speed);
- }
- if((key & BUTTON3) || RGBflag) //按键3改变8266板上RGB灯状态
- {
- RGBflag = 0;
-
- RGBMode++;
- if(RGBMode == 1) AT_Send(AT_COMM_R_ON);
- else if(RGBMode == 2) AT_Send(AT_COMM_R_OFF);
- else if(RGBMode == 3) AT_Send(AT_COMM_G_ON);
- else if(RGBMode == 4) AT_Send(AT_COMM_G_OFF);
- else if(RGBMode == 5) AT_Send(AT_COMM_B_ON);
- else if(RGBMode == 6) AT_Send(AT_COMM_B_OFF);
- else RGBMode = 0;
- }
-
- if(key) Log_printf("\r\nLedMode = %d Speed = %d", LedMode, speed);
- key = 0;
- }
- }
- //---------------------------------------------------------------------------- End
复制代码
2.与ESP8266的通讯
发送数据到ESP8266时,由M4分别发送命令给M0,M0再把收到的命令分别转换成AT指令,通过UART发送给ESP8266;接收数据时,M0把接收到的8266的数据根据通讯协议,解析成各种指令,再发送给M4,由M4来执行指令。
发送AT命令:
- const char * AT_COMM1_STR = "AT+CIPMUX=1\r\n";
- const char * AT_COMM2_STR = "AT+LANSTART\r\n";
- const char * AT_COMM3_STR = "AT+CIPSERVER=1,5000\r\n";
- const char * AT_COMM_R_ON_STR = "AT+CIOWRITE=15,1\r\n"; // RGB红灯亮
- const char * AT_COMM_R_OFF_STR = "AT+CIOWRITE=15,0\r\n"; // RGB红灯灭
- const char * AT_COMM_G_ON_STR = "AT+CIOWRITE=12,1\r\n"; // RGB绿灯亮
- const char * AT_COMM_G_OFF_STR = "AT+CIOWRITE=12,0\r\n"; // RGB绿灯灭
- const char * AT_COMM_B_ON_STR = "AT+CIOWRITE=13,1\r\n"; // RGB蓝灯亮
- const char * AT_COMM_B_OFF_STR = "AT+CIOWRITE=13,0\r\n"; // RGB蓝灯灭
- void AT_Send(int32_t comm)
- {
- switch(comm & 0x0f)
- {
- case AT_COMM1: Driver_USART5.Send(AT_COMM1_STR, strlen(AT_COMM1_STR)); break;
- case AT_COMM2: Driver_USART5.Send(AT_COMM2_STR, strlen(AT_COMM2_STR)); break;
- case AT_COMM3: Driver_USART5.Send(AT_COMM3_STR, strlen(AT_COMM3_STR)); break;
- case AT_COMM_R_ON: Driver_USART5.Send(AT_COMM_R_ON_STR, strlen(AT_COMM_R_ON_STR)); break;
- case AT_COMM_R_OFF: Driver_USART5.Send(AT_COMM_R_OFF_STR, strlen(AT_COMM_R_OFF_STR)); break;
- case AT_COMM_G_ON: Driver_USART5.Send(AT_COMM_G_ON_STR, strlen(AT_COMM_G_ON_STR)); break;
- case AT_COMM_G_OFF: Driver_USART5.Send(AT_COMM_G_OFF_STR, strlen(AT_COMM_G_OFF_STR)); break;
- case AT_COMM_B_ON: Driver_USART5.Send(AT_COMM_B_ON_STR, strlen(AT_COMM_B_ON_STR)); break;
- case AT_COMM_B_OFF: Driver_USART5.Send(AT_COMM_B_OFF_STR, strlen(AT_COMM_B_OFF_STR)); break;
- }
- }
复制代码 接收解析8266数据:
- int32_t AT_Receive(void)
- {
- static char buf[8];
- static char i = 0;
- static char t;
- int32_t ret=USART5_Receive(&t, 1);
- if(ret != 0) return 0;
- buf[i] = t;
- ret = 0;
- if(buf[0] == '[')
- {
- if(buf[i] == ']')
- {
- if(buf[1] == 'K')
- {
- if((buf[2] >= '0') && (buf[2] <= '7'))
- {
- ret = LED_ON_COMM | (buf[2] & 0x0F);
- }
- }
- else if(buf[1] == 'G')
- {
- if((buf[2] >= '0') && (buf[2] <= '7'))
- {
- ret = LED_OFF_COMM | (buf[2] & 0x0F);
- }
- }
- else if(buf[1] == '+')
- {
- LedMode = 0;
- ret = LED_ZZ_COMM;
- }
- else if(buf[1] == '-')
- {
- LedMode = 1;
- ret = LED_ZZ_COMM;
- }
- else if((buf[1] == 'S') && (buf[2] == '+'))
- {
- if(speed > 0) speed --;
- ret = SP_COMM_FLAG | speed;
- }
- else if((buf[1] == 'S') && (buf[2] == '-'))
- {
- if(speed < 50) speed ++;
- ret = SP_COMM_FLAG | speed;
- }
- else if(buf[1] == 'R')
- {
- RGBflag = 1;
- }
-
- i = 0;
- buf[0] = 0;
- }
- else
- {
- i++;
- if(i > 6)
- {
- i = 0;
- buf[0] = 0;
- }
- }
- }
- return ret;
- }
复制代码
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灯。
演示:
动图有点大,请耐心等待图片加载。。。
按键Key0:切换流水灯方向。
连续按Key1减缓流水灯速度,连续按Key2加快流水灯速度。
按Key3,依次点亮关闭ESP8266板上RGB灯的红绿蓝状态。
在手机上使用网络调试助手连接ESP8266,TCP客户端模式连接ESP8266的IP端口。
发送命令[R]控制RGB灯,效果和按键Key3相同。
手机控制54114开发板LED演示。依次发送以下命令:
[K1]:进入LED单独控制模式,点亮LED1。
[K5]:点亮LED5。
[G5]:关闭LED5。
[S+]:进入流水灯模式,流水灯正转。
|
|