dvd1478

  • 2019-04-16
  • 加入了学习《Hinton机器学习与神经网络》,观看 Why do we need machine learning

  • 2019-03-31
  • 发表了主题帖: 【NXP Rapid IoT评测】经典贪吃蛇 纯手打

    NXP Rapid IoT 原来调用的是EWWIM做显示架构的,利用原来的架构,通过 ATMO_Status_t GluttonousSnake_onDisplayed(ATMO_Value_t *in, ATMO_Value_t *out)进行自己的任务 ATMO_Status_t GluttonousSnake_onDisplayed(ATMO_Value_t *in, ATMO_Value_t *out) {         SX9500Touch_DisableAbilityHandle();         GluttonousSnakeInit();         ATMO_PLATFORM_DebugUsbPrint("%s\r\n",__FUNCTION__);         return ATMO_Status_Success;     }复制代码 GluttonousSnake 是在 Rapid IOT Studio 拖拉出来的显示模块的命名,根据自己实际情况进行修改。 现在只做了一个架框,蛇可以动,能吃食物,大概效果如果 画边界 //画一个蛇的最小单位 uint16_t Trun_On_Point(uint16_t x, uint16_t y, uint16_t size) {         GUI_FillRect(x, y, x + size, y + size);         return size; } //擦去一个蛇的最小单位 uint16_t Trun_Off_Point(uint16_t x, uint16_t y, uint16_t size) {         GUI_ClearRect(x, y, x + size, y + size);         return size; } static void CreateMap(void) {         uint16_t ucV_XSize = 0;         uint16_t ucV_YSize = 0;         uint16_t i = 0;         ucV_XSize = LCD_GetXSize();         ucV_YSize = LCD_GetYSize();         //ATMO_PLATFORM_DebugUsbPrint("LCD X:%d Y:%d\r\n",ucV_XSize,ucV_YSize);         GUI_SetColor(GUI_RED);  //画笔颜色         //GUI_SetPenSize(8);      //设置笔大小,5pixel粗线         //GUI_DrawRect(2,2,ucV_XSize-2,ucV_YSize-2);         //GUI_DrawLine(0,8, ucV_XSize-8, 8);         for (i = 0; i < ucV_XSize; i += 4) {    //打印上下边框                 //GUI_DispStringAt("A", i, 0);                 //GUI_DispStringAt("A", i, ucV_YSize);                 Trun_On_Point(i, 0, 2);                 Trun_On_Point(i, ucV_YSize - 1 - 2, 2);         }         for (i = 0; i < ucV_YSize; i += 4) {        //打印左右边框                 //GUI_DispStringAt("A", 0, i);                 //GUI_DispStringAt("A", ucV_XSize, i);                 Trun_On_Point(0, i, 2);                 Trun_On_Point(ucV_XSize - 1 - 2, i, 2);         }         //GUI_Exec(); }复制代码 画蛇与按键的操作回调函数 static void Snake_Init(void) {         uint8_t i;         snake.longth = 3;            //初始化长度为3         snake.isLive = 1;            //蛇是活着的         snake.score = 0; //当前的分为0         food.flag = 1;         for (i = 0; i < snake.longth; i++) {                 snake.XPos[i] = V_Snake_Size * 5 + V_Snake_Size * i;                 snake.YPos[i] = V_Snake_Size * 5;         }         for (i = 0; i < snake.longth; i++) {                 Trun_On_Point(snake.XPos[i], snake.YPos[i], V_Snake_Size);         }         ATMO_SX9500_RegisterTouchedCallback(SX9500_Touched_Down, SnakeDirKeyDown);         ATMO_SX9500_RegisterTouchedCallback(SX9500_Touched_Up, SnakeDirKeyUp);         ATMO_SX9500_RegisterTouchedCallback(SX9500_Touched_Left, SnakeDirKeyLeft);         ATMO_SX9500_RegisterTouchedCallback(SX9500_Touched_Right, SnakeDirKeyRight); } static void SnakeDirKeyLeft(void *value) {         uint8_t ucV_Key = 0;         ucV_Key = V_Dir_Left;         //ATMO_PLATFORM_DebugUsbPrint("%s\r\n",__FUNCTION__);         xQueueSend(hGlutonousSnakeKeyQueue, (void * ) &ucV_Key, (TickType_t )10); } static void SnakeDirKeyRight(void *value) {         uint8_t ucV_Key = 0;         ucV_Key = V_Dir_Right;         //ATMO_PLATFORM_DebugUsbPrint("%s\r\n", __FUNCTION__);         xQueueSend(hGlutonousSnakeKeyQueue, (void * ) &ucV_Key, (TickType_t )10); } static void SnakeDirKeyDown(void *value) {         uint8_t ucV_Key = 0;         ucV_Key = V_Dir_Down;         //ATMO_PLATFORM_DebugUsbPrint("%s\r\n", __FUNCTION__);         xQueueSend(hGlutonousSnakeKeyQueue, (void * ) &ucV_Key, (TickType_t )10); } static void SnakeDirKeyUp(void *value) {         uint8_t ucV_Key = 0;         ucV_Key = V_Dir_Up;         //ATMO_PLATFORM_DebugUsbPrint("%s\r\n", __FUNCTION__);         xQueueSend(hGlutonousSnakeKeyQueue, (void * ) &ucV_Key, (TickType_t )10); } 复制代码 蛇运行 bool SnakeIsDead(void) {         if ((snake.XPos[snake.longth - 1] = LCD_GetXSize())                         || (snake.YPos[snake.longth - 1] = LCD_GetYSize())) {                 snake.isLive = 0;         }         if (snake.isLive != 0) {                 return false;         }         return false; } void Snake_Run(uint8_t ucV_Dir) {         uint8_t i;         //for (i = 0; i < snake.longth; i++) {         //        Trun_Off_Point(snake.XPos[i], snake.YPos[i], V_Snake_Size);         //}         Trun_Off_Point(snake.XPos[0], snake.YPos[0], V_Snake_Size);        //去尾         for (i = 0; i < snake.longth - 1; i++) {                 snake.XPos[i] = snake.XPos[i + 1];                 snake.YPos[i] = snake.YPos[i + 1];         }         switch (ucV_Dir) {         case V_Dir_Right: {                 snake.XPos[snake.longth - 1] = snake.XPos[snake.longth - 2]                                 + V_Snake_Size + 1;                 snake.YPos[snake.longth - 1] = snake.YPos[snake.longth - 2] + 0;                 //Trun_On_Point(snake.XPos[snake.longth - 1], snake.YPos[snake.longth - 1], V_Snake_Size);                 break;         }         case V_Dir_Left: {                 snake.XPos[snake.longth - 1] = snake.XPos[snake.longth - 2]                                 - V_Snake_Size - 1;                 snake.YPos[snake.longth - 1] = snake.YPos[snake.longth - 2] + 0;                 //Trun_On_Point(snake.XPos[snake.longth - 1], snake.YPos[snake.longth - 1], V_Snake_Size);                 break;         }         case V_Dir_Down: {                 snake.XPos[snake.longth - 1] = snake.XPos[snake.longth - 2] + 0;                 snake.YPos[snake.longth - 1] = snake.YPos[snake.longth - 2]                                 + V_Snake_Size + 1;                 //Trun_On_Point(snake.XPos[snake.longth - 1], snake.YPos[snake.longth - 1], V_Snake_Size);                 break;         }         case V_Dir_Up: {                 snake.XPos[snake.longth - 1] = snake.XPos[snake.longth - 2] + 0;                 snake.YPos[snake.longth - 1] = snake.YPos[snake.longth - 2]                                 - V_Snake_Size - 1;                 //Trun_On_Point(snake.XPos[snake.longth - 1], snake.YPos[snake.longth - 1], V_Snake_Size);                 break;         }         default:                 break;         }         //for (i = 0; i < snake.longth; i++) {         //        Trun_On_Point(snake.XPos[i], snake.YPos[i], V_Snake_Size);         //}         if (SnakeIsDead()) {                 for (i = 0; i < snake.longth; i++) {                         Trun_Off_Point(snake.XPos[i], snake.YPos[i], V_Snake_Size);                 }         } else {                 Trun_On_Point(snake.XPos[snake.longth - 1],                                 snake.YPos[snake.longth - 1], V_Snake_Size);         } }复制代码 蛇吃食物 void Eat_Food(void) {         //uint8_t length[20]; //用于保存要显示的分数和长度         uint8_t i;         /*************************判断蛇是否吃到食物**********************/         //if ((snake.XPos[snake.longth - 1] == food.x)         //                && (snake.YPos[snake.longth - 1] == food.y)) {         if ( (D_IsInCCInterval(snake.XPos[snake.longth - 1], food.x,                         snake.XPos[snake.longth - 1] +V_Snake_Size)                         && D_IsInCCInterval(snake.YPos[snake.longth - 1], food.y,                                         snake.YPos[snake.longth - 1] +V_Snake_Size))                         || ( D_IsInCCInterval(food.x , snake.XPos[snake.longth - 1] , food.x +V_Snake_Size)                                         && D_IsInCCInterval(food.y, snake.YPos[snake.longth - 1],                                                         food.y +V_Snake_Size))  ) {                 snake.longth++;                 snake.score += 5;                 snake.XPos[snake.longth - 1] = food.x;                 snake.YPos[snake.longth - 1] = food.y;                 Trun_On_Point(snake.XPos[snake.longth - 1],                                 snake.YPos[snake.longth - 1], V_Snake_Size);                 food.flag = 1;         }         if (food.flag == 1) {                 while (1) {                         food.x =                                         rand() % (LCD_GetXSize() - V_Snake_Size * 2) + V_Snake_Size;                         food.y =                                         rand() % (LCD_GetYSize() - V_Snake_Size * 2) + V_Snake_Size;                         for (i = 0; i < snake.longth; i++) { //判断产生的食物是否和蛇身重合                                 if ((food.x == snake.XPos[i]) && (food.y == snake.YPos[i]))                                         break;                         }                         if (i == snake.longth) {                                 ATMO_PLATFORM_DebugUsbPrint("Create Food:%d %d\r\n", food.x,                                                 food.y);                                 food.flag = 0;                                 Trun_On_Point(food.x, food.y, V_Snake_Size);                                 break;                         }                 }         } }复制代码 对应的任务函数 void GluttonousSnakeTask(uint32_t param) {         BaseType_t xResult;         const TickType_t xMaxBlockTime = pdMS_TO_TICKS(300); /* 设置最大等待时间为 300ms */         uint8_t ucQueueKeyMsg;         /* Initialize GUI */         while (1) {                 xResult = xQueueReceive(hGlutonousSnakeKeyQueue, /* 消息队列句柄 */                 (void *)&ucQueueKeyMsg, /* 存储接收到的数据到变量 ucQueueMsgValue 中 */                 (TickType_t)xMaxBlockTime);/* 设置阻塞时间 */                 //vTaskDelay((TickType_t)xMaxBlockTime);                 if (xResult == pdPASS) {                         Snake_Run(ucQueueKeyMsg);                         Eat_Food();                 }         } }复制代码 此内容由EEWORLD论坛网友dvd1478原创,如需转载或用于商业用途需征得作者同意并注明出处

  • 2019-03-27
  • 加入了学习《FreeRTOS源码详解(正点原子)》,观看 第29.1讲 FreeRTOS任务调度器开启(上)

  • 2019-03-24
  • 发表了主题帖: 【NXP Rapid IoT评测】FreeRTOS调试方法(任务执行情况输出)

              NXP Rapid IoT源代码中很丰富,虽然知道使用FreeRTOS的但是代码的嵌套异常的复杂,对分析起来带来了困难。所以想通过FreeRTOS自身的vTaskList与 vTaskGetRunTimeStats 输出自身运行任务的情况          效果如下: 上面截图中打印出来的任务状态字母 B, R, D, S 对应如下含义: #define tskBLOCKED_CHAR         ( 'B' )    任务阻塞 #define tskREADY_CHAR              ( 'R' )    任务就绪 #define tskDELETED_CHAR          ( 'D' )    任务删除 #define tskSUSPENDED_CHAR     ( 'S' )    任务挂起 另外要注意剩余栈的单位是 word,即 4 字节。 一、修改宏 .\RapidIot_Base\middleware\wireless\framework\Common\rtos\FreeRTOS\config\FreeRTOSConfig.h 修改以下宏 /* Run time and task stats gathering related definitions. */ #define configUSE_TRACE_FACILITY                                   1 #define configGENERATE_RUN_TIME_STATS                           1 #define configUSE_STATS_FORMATTING_FUNCTIONS           1 /* Ensure stdint is only used by the compiler, and not the assembler. */ #if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)   #include   extern volatile uint32_t ulHighFrequencyTimerTicks; #endif #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()  (ulHighFrequencyTimerTicks = 0ul) #define portGET_RUN_TIME_COUNTER_VALUE()           ulHighFrequencyTimerTicks复制代码 二、添加以下代码 /* ********************************************************************************************************* * *        模块名称 : FreeRTOS任务信息 *        文件名称 : *        版    本 : V1.0 *        说    明 : 为了获取FreeRTOS的任务信息,需要创建一个定时器,这个定时器的时间基准精度要高于 *              系统时钟节拍。这样得到的任务信息才准确。 *              本文件提供的函数仅用于测试目的,切不可将其用于实际项目,原因有两点: *               1. FreeRTOS的系统内核没有对总的计数时间做溢出保护。 *               2. 定时器中断是50us进入一次,比较影响系统性能。 *              -------------------------------------------------------------------------------------- *              本文件使用的是32位变量来保存50us一次的计数值,最大支持计数时间: *              2^32 * 50us / 3600s = 59.6分钟。使用中测试的任务运行计数和任务占用率超过了59.6分钟将不准确。 * * ********************************************************************************************************* */ #include #include "fsl_pit.h" #include "clock_config.h" #include "fsl_os_abstraction.h" #include "fsl_os_abstraction_free_rtos.h" //#include "cmsis_os.h" #include "FreeRTOS.h" #include "task.h" #include "timers.h" #include "queue.h" #include "semphr.h" #include "event_groups.h" #include "shell.h" #include "atmosphere_platform.h" /* 定时器频率,50us一次中断 */ #define  timerINTERRUPT_FREQUENCY        20000 /* 中断优先级 */ #define  timerHIGHEST_PRIORITY                2 /* 被系统调用 */ volatile uint32_t ulHighFrequencyTimerTicks = 0UL; static int8_t shell_cmdTaskInfo(uint8_t argc, char * argv[]); const cmd_tbl_t CommandTask_Ver = {       .name = "taskinfo",         .maxargs = 2,         .repeatable = 1,         .cmd = shell_cmdTaskInfo,         .usage = "print FreeRTOS Info ", #if SHELL_USE_AUTO_COMPLETE         .complete = NULL, #endif         .help = NULL }; static int8_t shell_cmdTaskInfo(uint8_t argc, char * argv[]) {     char* pcWriteBuffer=NULL;     pcWriteBuffer = (char*) ATMO_Malloc(512);     if (pcWriteBuffer)     {         shell_write("=================================================\r\n");         shell_write("Task            State  Prio  ReStack  Num\r\n");         vTaskList((char *) pcWriteBuffer);         shell_writeN(pcWriteBuffer,strlen(pcWriteBuffer));         shell_write("\r\nTask            Count           Usage\r\n");         vTaskGetRunTimeStats((char *) pcWriteBuffer);         shell_writeN(pcWriteBuffer,strlen(pcWriteBuffer));         ATMO_Free(pcWriteBuffer);     } else {         shell_write("FreeRtos TaskInfo Error\r\n");     }     return CMD_RET_SUCCESS; } /* ********************************************************************************************************* *        函 数 名: vSetupTimerTest *        功能说明: 创建定时器 *        形    参: 无 *        返 回 值: 无 ********************************************************************************************************* */ void vAFreeRtosTaskInfoInit(void) {     /* Structure of initialize PIT */     pit_config_t pitConfig;     /*      * pitConfig.enableRunInDebug = false;      */     PIT_GetDefaultConfig(&pitConfig);     /* Init pit module */     PIT_Init(PIT, &pitConfig);     /* Set timer period for channel 0 */     PIT_SetTimerPeriod(PIT, kPIT_Chnl_0,             USEC_TO_COUNT(50U, CLOCK_GetFreq(kCLOCK_BusClk)));     /* Enable timer interrupts for channel 0 */     PIT_EnableInterrupts(PIT, kPIT_Chnl_0, kPIT_TimerInterruptEnable);     /* Enable at the NVIC */     EnableIRQ(PIT0_IRQn);     shell_register_function((cmd_tbl_t *)&CommandTask_Ver); } /* ********************************************************************************************************* *        函 数 名: PIT0_IRQHandler *        功能说明: PIT0中断服务程序。 *        形    参: 无 *        返 回 值: 无 ********************************************************************************************************* */ void PIT0_IRQHandler(void) {     /* Clear interrupt flag.*/     PIT_ClearStatusFlags(PIT, kPIT_Chnl_0, kPIT_TimerFlag);     ulHighFrequencyTimerTicks++; } /********************************************* (END OF FILE) *********************************/ 复制代码 调用初始化函数void vAFreeRtosTaskInfoInit(void),然后通过串口输出 taskinfo,就能输出相应的任务情况 通过上述的调试,获取相应的创建任务的情况 以及相关的任务函数 分别如下: 1、 .\RapidIot_Base\middleware\wireless\framework\OSAbstraction\Source\fsl_os_abstraction_free_rtos.c int main (void) 创建 startup_task 任务 2、 .\RapidIot_Base\rtos\freertos\Source\tasks.c void vTaskStartScheduler( void )创建  IDLE  任务 3、 .\RapidIot_Base\rtos\freertos\Source\timers.c BaseType_t xTimerCreateTimerTask( void ) 创建 prvTimerTask任务 4、 .\app_src\app_emwin.c void emWinTaskInit(void)创建  emWinTask  任务 5、 .\RapidIot_Base\middleware\wireless\framework\SerialManager\Source\SerialManager.c void SerialManager_Init( void ) 创建 SerialManagerTask 任务 6、 .\RapidIot_Base\middleware\wireless\framework\TimersManager\Source\TimersManager.c void TMR_Init(void)  创建 TMR_Task任务 7、 .\RapidIot_Base\middleware\wireless\framework\SerialManager\Source\USB_VirtualCom\virtual_com.c void* VirtualCom_Init(uint8_t param)创建  USB_DeviceTask任务 8、 .\gpio\gpio_mk64f.c ATMO_GPIO_Status_t ATMO_MK64F_GPIO_Init(ATMO_DriverInstanceData_t *instance) 创建 ATMO_MK64F_GPIO_RXQueueChecker  ATMO_MK64F_GPIO_ButtonResetChecker任务 9、 .\interval\interval_mk64f.c ATMO_INTERVAL_Status_t ATMO_MK64F_INTERVAL_Init(ATMO_DriverInstanceData_t *instance) ATMO_INTERVAL_Status_t ATMO_MK64F_INTERVAL_AddCallbackInterval(ATMO_DriverInstanceData_t *instance, ATMO_Callback_t cb, unsigned int interval, ATMO_INTERVAL_Handle_t *intervalHandle) 创建 intervalTask 任务 此内容由EEWORLD论坛网友dvd1478原创,如需转载或用于商业用途需征得作者同意并注明出处

  • 2019-03-17
  • 发表了主题帖: 【NXP Rapid IoT评测】I2C程序小bug

    上一篇 解决了I2C死锁解除的方法, 【NXP Rapid IoT评测】触摸按键没有反应——I2C死锁解除方法 http://bbs.eeworld.com.cn/forum. ... 1480&fromuid=194541。 但是总线上挂载的外设多时,有时会遇到外设失灵的情况,后来深入分析代码,出现问题在于 ATMO_Platform_I2C_Master_Transfer 这个函数上 static ATMO_I2C_Status_t ATMO_Platform_I2C_Master_Transfer(                 i2c_direction_t direction, kI2C_Blocking_t blocking, uint32_t instance,                 uint16_t slaveAddress, const uint8_t* cmdBytes, uint16_t numCmdBytes,                 uint8_t* dataBytes, uint16_t numDataBytes) {         status_t platformStatus = kStatus_Fail;         i2c_master_transfer_t masterStructure;         uint32_t cmd;         if (instance > MK64F_NUM_I2C_INSTANCES) {                 return ATMO_I2C_Status_NotSupported;         }         if (ATMO_Platform_I2C_Peripheral[instance].operatingMode                         == ATMO_I2C_OperatingMode_Slave) {                 return ATMO_I2C_Status_Invalid;         }         if (numCmdBytes > 4) {                 return ATMO_I2C_Status_NotSupported;         }         if ((dataBytes == NULL) || (numDataBytes == 0)) {                 return ATMO_I2C_Status_Invalid;         }         // if either cmdBytes or numCmdBytes is null/zero then set both to null/zero         if (cmdBytes == NULL) {                 numCmdBytes = 0;         } else if (numCmdBytes == 0) {                 cmdBytes = NULL;         }         if (numCmdBytes == 1) {                 cmd = cmdBytes[0];         } else if (numCmdBytes == 2) {                 cmd = (cmdBytes[0] transfer.direction == kI2C_Read)                                 && (status == kStatus_Success)) {                         I2C_MasterTransferGetCount(base, handle, &xferCount);                         masterXfer.event = ATMO_I2C_MasterEvent_Complete;                         masterXfer.data = handle->transfer.data - xferCount;                         masterXfer.dataSize = xferCount;                         if (callback != NULL) {                                 callback(&masterXfer, userData);                         }                 } else {                         if (callback != NULL) {                                 callback(&masterXfer, userData);                         }                 }         }         /* Signal transfer failure when received any other status. */         if ((status == kStatus_I2C_Nak) || (status == kStatus_I2C_Addr_Nak)                         || (status == kStatus_I2C_ArbitrationLost)                         || (status == kStatus_I2C_Timeout)) {                 nakFlag[instance] = true;         } }复制代码 实现阻塞为读写。 同时提供一个扫描I2C总线上设备的代码 ATMO_I2C_Status_t ATMO_I2C_Scan(ATMO_DriverInstanceHandle_t instance) {         uint8_t cmdBuf[2]={0};         uint8_t readBuf[1]={0};         uint8_t slaveAddress=0;         ATMO_I2C_Status_t status=ATMO_I2C_Status_Unknown;         ATMO_PLATFORM_DebugUsbPrint("Driver On I2C%d Line:\r\n    ",instance);         for(slaveAddress= 0x00;slaveAddress

  • 2019-03-16
  • 加入了学习《优化变压器设计来改进反激式变换器的效率和EMI性能》,观看 1.5 减小反激式变压器的EMI性能

  • 加入了学习《优化变压器设计来改进反激式变换器的效率和EMI性能》,观看 1.4 反激式变压器的漏感和嵌位电压

  • 加入了学习《优化变压器设计来改进反激式变换器的效率和EMI性能》,观看 1.3 反激式变压器的铜损

  • 加入了学习《优化变压器设计来改进反激式变换器的效率和EMI性能》,观看 1.2 反激式变压器的磁心损耗?

  • 加入了学习《优化变压器设计来改进反激式变换器的效率和EMI性能》,观看 1.1 反激式变压器的概论

  • 加入了学习《工业及汽车系统的低EMI电源变换器设计》,观看 EMI 优化技巧小结

  • 加入了学习《工业及汽车系统的低EMI电源变换器设计》,观看 通过增加 EMI 滤波器有效降低 EMI

  • 加入了学习《工业及汽车系统的低EMI电源变换器设计》,观看 通过频率抖动有效降低 EMI

  • 加入了学习《工业及汽车系统的低EMI电源变换器设计》,观看 通过控制开关点的 Slew Rate 有效降低 EMI

  • 加入了学习《工业及汽车系统的低EMI电源变换器设计》,观看 通过优化 PCB layout 有效降低 EMI

  • 加入了学习《工业及汽车系统的低EMI电源变换器设计》,观看 降低开关电源EMI干扰的方法

  • 加入了学习《工业及汽车系统的低EMI电源变换器设计》,观看 工业及汽车运用DCDC的主要特点

  • 加入了学习《工业及汽车系统的低EMI电源变换器设计》,观看 课程概览

  • 2019-03-10
  • 回复了主题帖: 恩智浦Rapid IoT套件有奖评测颁奖啦~期待2019年江湖再见,一起成长

    恭喜各位获奖者,惭愧了,到后边没有时间完成当时的评测计划。至前的失败在于太过依赖Rapid IOT Studio官网https://rapid-iot-studio.nxp.com。那网站实在太难登录,同时也低评了项目的容易性,高估了自己的能力。看了网友的测试,突然有了思路,其实Rapid IOT Studio就是一个原理性的设计,更多的情况还得通过离线性优化代码。不想没有做出什么东西,就退了,故申请多使用两个月,最终目标用离线型MCUXpresso IDE开发一个小游戏。每周小目标是发布一篇关于Rapid IoT套件的开发分享。 3.10分享【NXP Rapid IoT评测】触摸按键没有反应——I2C死锁解除方法 http://bbs.eeworld.com.cn/forum. ... 1480&fromuid=194541

  • 发表了主题帖: 【NXP Rapid IoT评测】触摸按键没有反应——I2C死锁解除方法

    NXP Rapid IoT  上用I2C1上挂了很多外设, I2C1: Sensors + Touch: FXOS8700, FXAS21002, MPL3115, ENS210, TSL25711, CCS811 (behind I2C switch), SX9500 I2C2: after I2C switch (...NTAG_I2C_EN): NT3H2211, A1006, A71 而且在开发过程中不何避免的复位重启Rapid IoT,造成了I2C时序混乱,同时又由于电池供电,而且I2C上所有设置并不是都全可以进行掉电或者硬件复件。 体现的现象   触摸按键没有反应,传感器没有数据,信号现象 SCL为高,SDA一直为低 死锁产生的原因分析如下:      在正常情况下,I2C总线协议能够保证总线正常的读写操作。但是,当I2C主设备异常复位时(看门狗动作,板上电源异常导致复位芯片动作,手动按钮复位等等)有可能导致I2C总线死锁产生。下面详细说明一下总线死锁产生的原因。       在I2C主设备进行读写操作的过程中.主设备在开始信号后控制SCL产生8个时钟脉冲,然后拉低SCL信号为低电平,在这个时候,从设备输出应答信号,将SDA信号拉为低电平。如果这个时候主设备异常复位,SCL就会被释放为高电平。此时,如果从设备没有复位,就会继续I2C的应答,将SDA一直拉为低电平,直到SCL变为低电平,才会结束应答信号。而对于I2C主设备来说.复位后检测SCL和SDA信号,如果发现SDA信号为低电平,则会认为I2C总线被占用,会一直等待SCL和SDA信号变为高电平。这样,I2C主设备等待从设备释放SDA信号,而同时I2C从设备又在等待主设备将SCL信号拉低以释放应答信号,两者相互等待,I2C总线进人一种死锁状态。同样,当I2C进行读操作,I2C从设备应答后输出数据,如果在这个时刻I2C主设备异常复位而此时I2C从设备输出的数据位正好为0,也会导致I2C总线进入死锁状态。 解锁方法如下: (1) 尽量选用带复位输人的I2C从器件。 (2) 将所有的从I2C设备的电源连接在一起,通过MOS管连接到主电源,而MOS管的导通关断由I2C主设备来实现。 (3) 在I2C从设备设计看门狗的功能。 (4) 在I2C主设备中增加I2C总线恢复程序。每次I2C主设备复位后,如果检测到SDA数据线被拉低,则控制I2C中的SCL时钟线产生9个时钟脉冲(针对8位数据的情况),这样I2C从设备就可以完成被挂起的读操作,从死锁状态中恢复过来。 (5) 在I2C总线上增加一个额外的总线恢复设备。 (6) 在I2C上串人一个具有死锁恢复的I2C缓冲器,如Linear公司的LTC4307。 硬件也设置好,而且并非每一个设备都满足上面的条件,只能选择方法(4),具体体现的代码如下: static void i2c_release_bus_delay(void) { #if 0 #define I2C1_RELEASE_BUS_COUNT 200U     uint32_t i = 0;     for (i = 0; i < I2C1_RELEASE_BUS_COUNT; i++)     {         __NOP();     } #else     App_WaitUsec(100); #endif } void BOARD_I2C1_ConfigurePins(void) {     /* Port C Clock Gate Control: Clock enabled */     CLOCK_EnableClock(kCLOCK_PortC);     const port_pin_config_t portc10_pinC7_config = {/* Internal pull-up resistor is enabled */                                                     kPORT_PullUp,                                                     /* Fast slew rate is configured */                                                     kPORT_FastSlewRate,                                                     /* Passive filter is disabled */                                                     kPORT_PassiveFilterDisable,                                                     /* Open drain is enabled */                                                     kPORT_OpenDrainEnable,                                                     /* Low drive strength is configured */                                                     kPORT_LowDriveStrength,                                                     /* Pin is configured as I2C1_SCL */                                                     kPORT_MuxAlt2,                                                     /* Pin Control Register fields [15:0] are not locked */                                                     kPORT_UnlockRegister};     /* PORTC10 (pin C7) is configured as I2C1_SCL */     PORT_SetPinConfig(PORTC, 10U, &portc10_pinC7_config);     const port_pin_config_t portc11_pinB7_config = {/* Internal pull-up resistor is enabled */                                                     kPORT_PullUp,                                                     /* Fast slew rate is configured */                                                     kPORT_FastSlewRate,                                                     /* Passive filter is disabled */                                                     kPORT_PassiveFilterDisable,                                                     /* Open drain is enabled */                                                     kPORT_OpenDrainEnable,                                                     /* Low drive strength is configured */                                                     kPORT_LowDriveStrength,                                                     /* Pin is configured as I2C1_SDA */                                                     kPORT_MuxAlt2,                                                     /* Pin Control Register fields [15:0] are not locked */                                                     kPORT_UnlockRegister};     /* PORTC11 (pin B7) is configured as I2C1_SDA */     PORT_SetPinConfig(PORTC, 11U, &portc11_pinB7_config); } void I2C1_ReleaseBus(void) {     uint8_t i = 0;     gpio_pin_config_t pin_config;     port_pin_config_t i2c_pin_config = {0};     /* Config pin mux as gpio */     i2c_pin_config.pullSelect = kPORT_PullUp;     i2c_pin_config.mux = kPORT_MuxAsGpio;     pin_config.pinDirection = kGPIO_DigitalOutput;     pin_config.outputLogic = 1U;     CLOCK_EnableClock(kCLOCK_PortC);     PORT_SetPinConfig(BOARD_INITPINS_I2C1_SCL_PORT, BOARD_INITPINS_I2C1_SCL_PIN, &i2c_pin_config);     PORT_SetPinConfig(BOARD_INITPINS_I2C1_SDA_PORT, BOARD_INITPINS_I2C1_SDA_PIN, &i2c_pin_config);     GPIO_PinInit(BOARD_INITPINS_I2C1_SCL_PORT, BOARD_INITPINS_I2C1_SCL_PIN, &pin_config);     GPIO_PinInit(BOARD_INITPINS_I2C1_SDA_PORT, BOARD_INITPINS_I2C1_SDA_PIN, &pin_config);     /* Drive SDA low first to simulate a start */     GPIO_PinWrite(BOARD_INITPINS_I2C1_SDA_PORT, BOARD_INITPINS_I2C1_SDA_PIN, 0U);     i2c_release_bus_delay();     /* Send 9 pulses on SCL and keep SDA high */     for (i = 0; i < 9; i++)     {         GPIO_PinWrite(BOARD_INITPINS_I2C1_SCL_PORT, BOARD_INITPINS_I2C1_SCL_PIN, 0U);         i2c_release_bus_delay();         GPIO_PinWrite(BOARD_INITPINS_I2C1_SDA_PORT, BOARD_INITPINS_I2C1_SDA_PIN, 1U);         i2c_release_bus_delay();         GPIO_PinWrite(BOARD_INITPINS_I2C1_SCL_PORT, BOARD_INITPINS_I2C1_SCL_PIN, 1U);         i2c_release_bus_delay();         i2c_release_bus_delay();     }     /* Send stop */     GPIO_PinWrite(BOARD_INITPINS_I2C1_SCL_PORT, BOARD_INITPINS_I2C1_SCL_PIN, 0U);     i2c_release_bus_delay();     GPIO_PinWrite(BOARD_INITPINS_I2C1_SDA_PORT, BOARD_INITPINS_I2C1_SDA_PIN, 0U);     i2c_release_bus_delay();     GPIO_PinWrite(BOARD_INITPINS_I2C1_SCL_PORT, BOARD_INITPINS_I2C1_SCL_PIN, 1U);     i2c_release_bus_delay();     GPIO_PinWrite(BOARD_INITPINS_I2C1_SDA_PORT, BOARD_INITPINS_I2C1_SDA_PIN, 1U);     i2c_release_bus_delay();     BOARD_I2C1_ConfigurePins(); }复制代码 初始上时钟后,就可以调用上述代码。 完整代码, 替换  工程文件\RapidIot_Base\board\board.c 此内容由EEWORLD论坛网友dvd1478原创,如需转载或用于商业用途需征得作者同意并注明出处

最近访客

< 1/2 >

统计信息

已有83人来访过

  • 芯币:2047
  • 好友:--
  • 主题:32
  • 回复:141
  • 课时:--
  • 资源:10

留言

你需要登录后才可以留言 登录 | 注册


bmyuan 2018-4-20
期待成为朋友   Q   158356574     我想了解一些电子方面的东西,还请相教
查看全部