嵌入式应用编程经验之谈-ESP8266引脚中断编程

    ESP8266相信这是目前关于嵌入式wifi系统解决方案的首选芯片。这里我之前也搞过庆科的wifi模块,他有自己的操作系统MICO也可以用keil开发,使用起来也很好上手,但是价格相差太大很多公司考虑成本问题无疑都会选ESP8266。 根据公司的项目需要,需要对ESP8266做一个SDK的项目开发,这里我需要用到外部引脚的双边沿中断触发。

  这里很感谢这位网友(也许现在将来)的帖子(http://blog.csdn.net/qq_15647227/article/details/52218286?locationNum=1)很详细的介绍了引脚中断需要用到的函数和函数介绍,写的很用心。这里我给出地址就不重复介绍他帖子中介绍的东西,而是分享一下我在完成这个项目中遇到的问题和怎么解决这些问题的。希望我写的东西也能对正在编程路上的小伙伴们有所帮助。

  问题一: 测试高低电平触发,这里无法正常触发中断,这里发现程序一直在进入中断,长期在中断函数中导致最后死机重启。

  问题分析:这里发现中断函数是可以进入的,但是一直在反复进入中断。这里可以进入中断也就说明我们至少开启中断的配置是正确的,打开了中断的入口。

 问题解决:这里经过量取中断脚的电压发现中断脚一直保持着中断的电平(低电平触发)。这里我们需要结合硬件图发现问题出现在引脚配置上。这里结合电路图,我们发现需要开启引脚的内部上拉,这样引脚默认情况下是高电平。

这里根据硬件图,无论上升沿还是下降沿,当TTL低电平时候构成回路,拉低TTL-1产生下降沿触发。这里我们需要结合自身的硬件做好端口的配置。


  嵌入式应用编程经验之谈-ESP8266引脚中断编程_第1张图片

                                                             图一:  引脚电路

		PIN_PULLUP_EN(PERIPHS_IO_MUX_GPIO5_U);        //使能上拉
		PIN_PULLUP_EN(PERIPHS_IO_MUX_GPIO4_U);
		PIN_PULLUP_EN(PERIPHS_IO_MUX_MTCK_U);
		PIN_PULLUP_EN(PERIPHS_IO_MUX_MTMS_U);          
		gpio_output_set(0,0,0,BIT5);                  //使能输入
		gpio_output_set(0,0,0,BIT4);
		gpio_output_set(0,0,0,BIT14);
		gpio_output_set(0,0,0,BIT13);

		gpio_output_set(0,0,0,BIT12);

 问题二:根据网友的帖子我们看到他只开了一路中断,这里根据项目我需要开四路中断。这里代码配置如何写?

 问题解决:这里我过程中也测试过多次才完成了正确的配置。这里的多个中断的配置需要分开配置,也就是把单个配置的逻辑代码重复操作,根据自己的需求跟换触发IO口的参数。这里我下面直接给出多路中断配置的代码和中断函数中如何区别哪路中断的代码逻辑。

void GPIO_ISR_Handler(void)
{
	  u32 pin_status=0;

	   pin_status = GPIO_REG_READ( GPIO_STATUS_ADDRESS );      /** 读取GPIO中断状态可以判断是那个端口的中断 */

	   ETS_GPIO_INTR_DISABLE();                            /** 关闭GPIO中断 */
                      
	   if ( pin_status&BIT(5) )   /*GPIO5的中断*/
	   {
	      
	   }
	   if ( pin_status&BIT(4))     /*GPIO4的中断*/
	   {
	  	    
	   }
	   if ( pin_status&BIT(13))        /*GPIO13的中断*/
	   {
	  	
           }
	   if ( pin_status&BIT(14))      /*GPIO14的中断*/
	   {
	  	
	   }
	   GPIO_REG_WRITE( GPIO_STATUS_W1TC_ADDRESS,  pin_status );   /** 清除GPIO中断标志 */
	   ETS_GPIO_INTR_ENABLE();                                   /** 开启GPIO中断 */

}


void ICACHE_FLASH_ATTR
GPIO_Input_Inter(void)
{

	    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO5_U, FUNC_GPIO5);    //定义管教功能  作GPIO使用
	    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO4_U, FUNC_GPIO4);
	    PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U,  FUNC_GPIO13);
	    PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U,  FUNC_GPIO14);

            PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U,  FUNC_GPIO12);
	    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0);

	     GPIO_DIS_OUTPUT(FUNC_GPIO5);  //使能输出功能
	     GPIO_DIS_OUTPUT(FUNC_GPIO4);
	     GPIO_DIS_OUTPUT(FUNC_GPIO13);
	     GPIO_DIS_OUTPUT(FUNC_GPIO14);

            //GPIO5中断配置 下面类推
	    ETS_GPIO_INTR_DISABLE();                             //中断失能
	    ETS_GPIO_INTR_ATTACH(&GPIO_ISR_Handler, NULL );     //注册中断函数
	    gpio_pin_intr_state_set( GPIO_ID_PIN(5), GPIO_PIN_INTR_ANYEDGE );            //设置中断方式
	    GPIO_REG_WRITE( GPIO_STATUS_W1TC_ADDRESS,  BIT(5));          /** 清除该引脚的GPIO中断标志 */
	    ETS_GPIO_INTR_ENABLE();                          //中断使能


	    ETS_GPIO_INTR_DISABLE();
	    ETS_GPIO_INTR_ATTACH(&GPIO_ISR_Handler, NULL );  //注册中断函数
	    gpio_pin_intr_state_set( GPIO_ID_PIN(4), GPIO_PIN_INTR_ANYEDGE );
	    GPIO_REG_WRITE( GPIO_STATUS_W1TC_ADDRESS,  BIT(4));
	    ETS_GPIO_INTR_ENABLE();

	    ETS_GPIO_INTR_DISABLE();
	    ETS_GPIO_INTR_ATTACH(&GPIO_ISR_Handler, NULL );  //注册中断函数  TTL1
	    gpio_pin_intr_state_set( GPIO_ID_PIN(13), GPIO_PIN_INTR_ANYEDGE );
	    GPIO_REG_WRITE( GPIO_STATUS_W1TC_ADDRESS,  BIT(13));
	    ETS_GPIO_INTR_ENABLE();


	    ETS_GPIO_INTR_DISABLE();
	    ETS_GPIO_INTR_ATTACH(&GPIO_ISR_Handler, NULL );  //注册中断函数
            gpio_pin_intr_state_set( GPIO_ID_PIN(14), GPIO_PIN_INTR_ANYEDGE );
	    GPIO_REG_WRITE( GPIO_STATUS_W1TC_ADDRESS,  BIT(14));
	    ETS_GPIO_INTR_ENABLE();


		PIN_PULLUP_EN(PERIPHS_IO_MUX_GPIO5_U);        //使能上拉
		PIN_PULLUP_EN(PERIPHS_IO_MUX_GPIO4_U);
		PIN_PULLUP_EN(PERIPHS_IO_MUX_MTCK_U);
		PIN_PULLUP_EN(PERIPHS_IO_MUX_MTMS_U);

		PIN_PULLUP_EN(PERIPHS_IO_MUX_MTDI_U);
		PIN_PULLUP_EN(PERIPHS_IO_MUX_GPIO0_U);


		gpio_output_set(0,0,0,BIT5);                  //使能输入
		gpio_output_set(0,0,0,BIT4);
		gpio_output_set(0,0,0,BIT14);
		gpio_output_set(0,0,0,BIT13);

		gpio_output_set(0,0,0,BIT12);
}
问题三:这个问题最为棘手,也调试了很长时间才发现问题所在。这里也感谢下面这位网友的帖子,这里我也给出链接,这位网友帖子中总结的常见问题,或许就是你遇到的问题之一。(http://bbs.eeworld.com.cn/thread-506728-1-1.html)这个帖子给我启发很大也让我发现了问题的原因。

问题分析:这里代码出现异常死机,并且死机重启后,我之前在falsh区域的数据也出现丢失。这里我也郁闷,死机或许是代码中的BUG导致的,怎么连falsh中的数据都会被修改。这里我也有想到关于falsh区域分配的问题。这里通过打印也一直发现不了问题的所在。

问题解决:这里需要需要的点是,在注册外部引脚的中断函数,我们不能使用ICACHE_FLASH_ATTR这个语句去定义中断函数。在中断函数中不要再调用带有“ICACHE_FLASH_ATTR”宏的函数,否则可能与 Flash 读写操作冲突。这里提到的Flash读写冲突也就和我现在遇到的问题吻合。

对于 ESP8266_Non-OS_SDK:

添加了“ICACHE_FLASH_ATTR”宏的函数,将存放在 IROM 中,CPU 仅在调用到它们的时候,将它们读到 cache 中运行;没有添加到“ICACHE_FLASH_ATTR”宏的函数,将在一开始上电运行时,就加载到 IRAM 中运行;由于空间有限,我们无法将所有代码都一次性加载到 IRAM 中运行,因此在大部分函数前添加到“ICACHE_FLASH_ATTR”宏,放在 IROM 中。

   这里遇到的问题也反映了我自身对ESP8266SDK开发的不熟练,这里每个人都有个过程。每次我们遇到问题的时候也就是我们成长的时候。

   本人一直相信不断交流,是提升自我重要的手段之一。本人也建有一个交流群(469602418)欢迎大家可以加入一起对自己遇到的问题交流。 

   





你可能感兴趣的:(嵌入式项目硬件编程-经验之谈,ESP8266,嵌入式,wifi)