stm32和esp8266程序资料分析
来源:互联网 发布:暗黑战神 源码分析 编辑:程序博客网 时间:2024/04/28 16:47
stm32和esp8266wifi模块的代码分析和讲解。
http://download.csdn.net/album/detail/2287
前段时间参加比赛,虽然我是负责的软件方面(我更喜欢软件开发,在软件反面的功法比硬件多多了),负责android,java电脑界面等系统的软件层,但是网关这块一直处理不了,不能实现硬件和软件的数据交流问题,由于我做的比较快,我就参加到了网关这块的工作(那个时候把stm32和esp8266联网称为网关…)。
今天,来分享我的检验,大家一起学习学习,不足之处还请提醒和让我一起学习学习。
我们选择的是stm32f103和esp8266,进行串口通信。
1,对stm32进行串口端的初始化。选择usart2串口,对其初始化。
/* Configure USART2 Tx (PA.02) as alternate function push-pull */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Configure USART2 Rx (PA.03) as input floating */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure);/* USART2 mode config */USART_InitStructure.USART_BaudRate = 115200; USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_Parity = USART_Parity_No ;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;USART_Init(USART2, &USART_InitStructure); /* 使能串口2接收中断 */USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);/* 使能串口2总线空闲中断 */USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);USART_Cmd(USART2, ENABLE);
注意选择115200的比特率*
为了方便可以把所以的都设置成115200,(不一定需要)
2,
这儿一定要修改。这是对esp8266的使能端口进行的处理,一定要正确,引脚的拉高和拉低很重要,这儿就是这个原因,我那个时候调试了很久很久。
/*定义一个GPIO_InitTypeDef类型的结构体*/ GPIO_InitTypeDef GPIO_InitStructure; /*开启GPIOA的外设时钟*/ RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE ); /* 配置WiFi模块的片选(CH)引脚复位重启(RST)引脚*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; /*设置引脚模式为通用推挽输出*/ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; /*设置引脚速率为50MHz */ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; /*调用库函数,初始化GPIOA*/ GPIO_Init( GPIOA, &GPIO_InitStructure ); /* 拉低WiFi模块的片选引脚 */ GPIO_SetBits( GPIOA, GPIO_Pin_0 ); /* 拉高WiFi模块的复位重启引脚 */ GPIO_SetBits( GPIOA, GPIO_Pin_1 );
3, 对端口进行控制的处理,这里对串口2进行申明,然后需要在4中的文件添加数据,
NVIC_InitTypeDef NVIC_InitStructure; /* Configure the NVIC Preemption Priority Bits */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);/* Enable the USART2 Interrupt */NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);
4, 在stm32f10x_it.c文件中的串口2的处理函数中添加这段代码。这儿是串口中断处理函数。当有中断的时候,这段代码吧收到
的数据进行存储。存储在结构体里面,在5中有说明,很重要的终端处理函数/。
void USART2_IRQHandler( void ){ char ch; //pStr = ESP8266_ReceiveString ( DISABLE ); if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) { ch = USART_ReceiveData( USART2 ); if( strEsp8266_Fram_Record .InfBit .FramLength < ( RX_BUF_MAX_LEN - 1 ) ) //预留1个字节写结束符 { strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ++ ] = ch; } }if ( USART_GetITStatus( USART2, USART_IT_IDLE ) == SET ) //数据帧接收完毕{ strEsp8266_Fram_Record .InfBit .FramFinishFlag = 1; ch = USART_ReceiveData( USART2 ); //由软件序列清除中断标志位(先读USART_SR,然后读USART_DR)
}
}
5,对应4中的结构体声明
个人觉得很重要,这样才可以在以后对数据收到的数据进行处理的时候,直接在结果体中进行取值和判断是否是想要的值,然后在进行相应的操作
extern struct STRUCT_USARTx_Fram //串口数据帧的处理结构体{ char Data_RX_BUF[ RX_BUF_MAX_LEN ]; union { __IO u16 InfAll; struct { __IO u16 FramLength :15; // 14:0 __IO u16 FramFinishFlag :1; // 15 } InfBit; }; } strPc_Fram_Record, strEsp8266_Fram_Record;extern struct STRUCT_USART1_1_Fram //串口数据帧的处理结构体{ char Data_RX_BUF[ RX_BUF_MAX_LEN ]; union { __IO u16 InfAll; struct { __IO u16 FramLength :15; // 14:0 __IO u16 FramFinishFlag :1; // 15 } InfBit; }; } strPc1_1_Fram_Record, str1_1esp8266;
6,下面是一个最重要的方法。很多出可以使用,对于串口的esp8266模块很大的用处
对于at指令来说,这段代码是这个程序的核心,可以用这段代码完成这个操作。
函数返回值是布尔类型的,可以在while()里面调用这段函数,这样可以实现
一直循环的进行cmd操作,直到这句话进行完成以后才跳出。这样保证能够使得
每一条at指令都能执行,对于while不能一次性执行的at指令,程序将会一直执行
这条at指令,直到执行完成。
/* * 函数名:ESP8266_Cmd * 描述 :对WF-ESP8266模块发送AT指令 * 输入 :cmd,待发送的指令 * reply1,reply2,期待的响应,为NULL表不需响应,两者为或逻辑关系 * waittime,等待响应的时间 * 返回 : 1,指令发送成功 * 0,指令发送失败 * 调用 :被外部调用 */ bool ESP8266_Cmd ( char * cmd, char * reply1, char * reply2, u32 waittime ) { strEsp8266_Fram_Record .InfBit .FramLength = 0; //从新开始接收新的数据包 ESP8266_Usart ( "%s\r\n", cmd ); if ( ( reply1 == 0 ) && ( reply2 == 0 ) ) //不需要接收数据 return true; Delay_ms ( waittime ); //延时 strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ] = '\0'; // PC_Usart ( "%s", strEsp8266_Fram_Record .Data_RX_BUF ); if ( ( reply1 != 0 ) && ( reply2 != 0 ) ) return ( ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply1 ) || ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply2 ) ); else if ( reply1 != 0 ) return ( ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply1 ) ); else return ( ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply2 ) ); }
6,介绍一个很重要的函数,在C语言里面的,strstr();
这个特别的重要。对于这个程序来说。可以判断结构体内接受到的数据是否有自己想要的值,
然后,做出对应的操作,这样实现了远程控制的作用。
列入: strstr(a,b);
判断字符窜,a中是否有b一样的字符串。如果有,就返回真。
strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply1 )
7,主动发送数据的函数。自己调用很好的使用。能达到很不错的效果,下面的函数里面有这个函数的调用的使用。
/* * 函数名:ESP8266_SendString * 描述 :WF-ESP8266模块发送字符串 * 输入 :enumEnUnvarnishTx,声明是否已使能了透传模式 * :pStr,要发送的字符串 * :ulStrLength,要发送的字符串的字节数 * :ucId,哪个ID发送的字符串 * 返回 : 1,发送成功 * 0,发送失败 * 调用 :被外部调用 // ESP8266_SendString ( DISABLE, cStrInput, ul, ( ENUM_ID_NO_TypeDef ) uc ); */bool ESP8266_SendString ( FunctionalState enumEnUnvarnishTx, char * pStr, u32 ulStrLength, ENUM_ID_NO_TypeDef ucId ){ char cStr [20]; bool bRet = false; if ( enumEnUnvarnishTx ) ESP8266_Usart ( "%s", pStr ); else { if ( ucId < 5 ) sprintf ( cStr, "AT+CIPSEND=%d,%d", ucId, ulStrLength + 2 ); else sprintf ( cStr, "AT+CIPSEND=%d", ulStrLength + 2 ); ESP8266_Cmd ( cStr, "> ", 0, 1000 ); bRet = ESP8266_Cmd ( pStr, "SEND OK", 0, 1000 ); } return bRet;}
8,函数主动接受的函数,这儿是主动接受的数据。
自己调用很好的使用。能达到很不错的效果,下面的函数里面有这个函数的调用的使用。
/* * 函数名:ESP8266_ReceiveString * 描述 :WF-ESP8266模块接收字符串 * 输入 :enumEnUnvarnishTx,声明是否已使能了透传模式 * 返回 : 接收到的字符串首地址 * 调用 :被外部调用 */char * ESP8266_ReceiveString ( FunctionalState enumEnUnvarnishTx ){ char * pRecStr = 0; strEsp8266_Fram_Record .InfBit .FramLength = 0; strEsp8266_Fram_Record .InfBit .FramFinishFlag = 0; while ( ! strEsp8266_Fram_Record .InfBit .FramFinishFlag ); strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ] = '\0'; if ( enumEnUnvarnishTx ) { if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, ">" ) ) pRecStr = strEsp8266_Fram_Record .Data_RX_BUF; } else { if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+IPD" ) ) pRecStr = strEsp8266_Fram_Record .Data_RX_BUF; } return pRecStr;}
9,,,,,,,,,,,,,,,,,
这是一个最整体的函数,作用是相当于对stm32驱动wifi模块,进行初始化,链接路由器账号,密码,以及端口号的设置。
很重要的一个函数。。。。。。。
/* * 函数名:ESP8266_STA_TCP_Client * 描述 :WF-ESP8266模块进行STA TCP Clien测试 * 输入 :无 * 返回 : 无 * 调用 :被外部调用 */void ESP8266_STA_TCP_Client ( void ){ char cStrInput [100] = { 0 }, * pStrDelimiter [2], * pBuf, * pStr; u8 uc = 0; u32 ul = 0; ESP8266_Choose ( ENABLE ); // PC_Usart ( "-1-----------------------------sss"); ESP8266_AT_Test (); ESP8266_Net_Mode_Choose ( STA ); ESP8266_Cmd ( "AT+CWLAP", "OK", 0, 5000 );/////////////////////// 处 理 登陆密码的操作 //////////////////////////////////////// PC_Usart ( "------------------------------sss"); ESP8266_password_join(); /* do { PC_Usart ( "\r\n请输入要连接的WiFi名称和密钥,输入格式为:名称字符+英文逗号+密钥字符+空格,点击发送\r\n" ); scanf ( "%s", cStrInput ); PC_Usart ( "\r\n稍等片刻 ……\r\n" ); pBuf = cStrInput; uc = 0; while ( ( pStr = strtok ( pBuf, "," ) ) != NULL ) { pStrDelimiter [ uc ++ ] = pStr; pBuf = NULL; } } while ( ! ESP8266_JoinAP ( pStrDelimiter [0], pStrDelimiter [1] ) ); *//////////////////////////////////////////////////////////////////////////////////////// ESP8266_Enable_MultipleId ( ENABLE );///////////////////////////////处理 tcp 服务连接的函数//////////////////////////////////////////// ESP8266_linkTCP_join(); /* 选择tcp/udp连接代码,以上修改为固定,在函数ESP8266_linkTCP_join()内。 do {g PC_Usart ( "\r\n请在电脑上将网络调试助手以TCP Server连接网络,并输入电脑的IP和端口号,输入格式为:电脑IP+英文逗号+端口号+空格,点击发送\r\n" ); scanf ( "%s", cStrInput ); PC_Usart ( "\r\n稍等片刻 ……\r\n" ); pBuf = cStrInput; uc = 0; while ( ( pStr = strtok ( pBuf, "," ) ) != NULL ) { pStrDelimiter [ uc ++ ] = pStr; pBuf = NULL; } } while ( ! ( ESP8266_Link_Server ( enumTCP, pStrDelimiter [0], pStrDelimiter [1], Multiple_ID_0 ) ) ); // && ESP8266_Link_Server ( enumTCP, pStrDelimiter [0], pStrDelimiter [1], Multiple_ID_1 ) && // ESP8266_Link_Server ( enumTCP, pStrDelimiter [0], pStrDelimiter [1], Multiple_ID_2 ) && // ESP8266_Link_Server ( enumTCP, pStrDelimiter [0], pStrDelimiter [1], Multiple_ID_3 ) && // ESP8266_Link_Server ( enumTCP, pStrDelimiter [0], pStrDelimiter [1], Multiple_ID_4 ) */ GPIO_ResetBits(GPIOC, GPIO_Pin_3); Delay_ms(1000); linktcp_LED_tell();linktcp_LED_tell();linktcp_LED_tell(); //LED_all_hei(); // GPIO_ResetBits(GPIOC, GPIO_Pin_3); /* if(usart1_rx_value==1){ PC_Usart ( "\r\n请输入端口ID%d要发送的字符串,输入格式为:字符串(不含空格)+空格,点击发送\r\n", uc ); scanf ( "%s", cStrInput ); ul = strlen ( cStrInput ); ESP8266_SendString ( DISABLE, cStrInput, ul, ( ENUM_ID_NO_TypeDef ) uc ); ESP8266_SendString ( DISABLE, cStrInput, ul, ( ENUM_ID_NO_TypeDef ) uc ); } */////////////////////////////////////////////////////////////////////////////////////////////////////////// for ( uc = 0; uc < 2; uc ++ ) { PC_Usart ( "\r\n请输入端口ID%d要发送的字符串,输入格式为:字符串(不含空格)+空格,点击发送\r\n", uc ); scanf ( "%s", cStrInput ); ul = strlen ( cStrInput ); // ESP8266_SendString ( DISABLE, cStrInput, ul, ( ENUM_ID_NO_TypeDef ) uc ); ESP8266_SendString ( DISABLE, cStrInput, ul, ( ENUM_ID_NO_TypeDef ) 0 ); PC_Usart ( "%s", strEsp8266_Fram_Record .Data_RX_BUF ); } PC_Usart ( "\r\n请在网络调试助手发送字符串\r\n" ); while (1) { ////////////////////////////// //接收电脑端的数据 pStr = ESP8266_ReceiveString ( DISABLE ); PC_Usart ( "%s", pStr ); /////////////////////////////////// //发送电脑端的数据 // scanf ( "%s", cStrInput ); // // ul = strlen ( str1_1esp8266.Data_RX_BUF ); // // ESP8266_SendString ( DISABLE, str1_1esp8266.Data_RX_BUF, ul, ( ENUM_ID_NO_TypeDef ) 0 ); // // PC_Usart ( "%s", str1_1esp8266 .Data_RX_BUF ); PC_Usart ( "\r\n输入格式为:字符串(不含空格)+空格,点击发送\r\n", uc ); // scanf ( "%s", cStrInput ); ul = strlen ( cStrInput ); ESP8266_SendString ( DISABLE, cStrInput, ul, ( ENUM_ID_NO_TypeDef ) 0 ); PC_Usart ( "%s", strEsp8266_Fram_Record .Data_RX_BUF ); }}
10,下面是一些相关函数的封装,吧at指令都封装在一起的函数体,不需要的话可以不在自己的函数里面添加。
/* * 函数名:ESP8266_UnvarnishSend * 描述 :配置WF-ESP8266模块进入透传发送 * 输入 :无 * 返回 : 1,配置成功 * 0,配置失败 * 调用 :被外部调用 */bool ESP8266_UnvarnishSend ( void ){ return ( ESP8266_Cmd ( "AT+CIPMODE=1", "OK", 0, 500 ) && ESP8266_Cmd ( "AT+CIPSEND", "\r\n", ">", 500 ) );}/* * 函数名:ESP8266_StartOrShutServer * 描述 :WF-ESP8266模块开启或关闭服务器模式 * 输入 :enumMode,开启/关闭 * :pPortNum,服务器端口号字符串 * :pTimeOver,服务器超时时间字符串,单位:秒 * 返回 : 1,操作成功 * 0,操作失败 * 调用 :被外部调用 */bool ESP8266_StartOrShutServer ( FunctionalState enumMode, char * pPortNum, char * pTimeOver ){ char cCmd1 [120], cCmd2 [120]; if ( enumMode ) { sprintf ( cCmd1, "AT+CIPSERVER=%d,%s", 1, pPortNum ); sprintf ( cCmd2, "AT+CIPSTO=%s", pTimeOver ); return ( ESP8266_Cmd ( cCmd1, "OK", 0, 500 ) && ESP8266_Cmd ( cCmd2, "OK", 0, 500 ) ); } else { sprintf ( cCmd1, "AT+CIPSERVER=%d,%s", 0, pPortNum ); return ESP8266_Cmd ( cCmd1, "OK", 0, 500 ); }}/* * 函数名:ESP8266_Link_Server * 描述 :WF-ESP8266模块连接外部服务器 * 输入 :enumE,网络协议 * :ip,服务器IP字符串 * :ComNum,服务器端口字符串 * :id,模块连接服务器的ID * 返回 : 1,连接成功 * 0,连接失败 * 调用 :被外部调用 */bool ESP8266_Link_Server ( ENUM_NetPro_TypeDef enumE, char * ip, char * ComNum, ENUM_ID_NO_TypeDef id){ char cStr [100] = { 0 }, cCmd [120]; switch ( enumE ) { case enumTCP: sprintf ( cStr, "\"%s\",\"%s\",%s", "TCP", ip, ComNum ); break; case enumUDP: sprintf ( cStr, "\"%s\",\"%s\",%s", "UDP", ip, ComNum ); break; default: break; } if ( id < 5 ) sprintf ( cCmd, "AT+CIPSTART=%d,%s", id, cStr); else sprintf ( cCmd, "AT+CIPSTART=%s", cStr ); return ESP8266_Cmd ( cCmd, "OK", "ALREAY CONNECT", 500 );}/* * 函数名:ESP8266_BuildAP * 描述 :WF-ESP8266模块创建WiFi热点 * 输入 :pSSID,WiFi名称字符串 * :pPassWord,WiFi密码字符串 * :enunPsdMode,WiFi加密方式代号字符串 * 返回 : 1,创建成功 * 0,创建失败 * 调用 :被外部调用 */bool ESP8266_BuildAP ( char * pSSID, char * pPassWord, char * enunPsdMode ){ char cCmd [120]; sprintf ( cCmd, "AT+CWSAP=\"%s\",\"%s\",1,%s", pSSID, pPassWord, enunPsdMode ); return ESP8266_Cmd ( cCmd, "OK", 0, 1000 );}/* * 函数名:ESP8266_JoinAP * 描述 :WF-ESP8266模块连接外部WiFi * 输入 :pSSID,WiFi名称字符串 * :pPassWord,WiFi密码字符串 * 返回 : 1,连接成功 * 0,连接失败 * 调用 :被外部调用 */bool ESP8266_JoinAP ( char * pSSID, char * pPassWord ){ char cCmd [120]; sprintf ( cCmd, "AT+CWJAP=\"%s\",\"%s\"", pSSID, pPassWord ); return ESP8266_Cmd ( cCmd, "OK", NULL, 7000 );}/* * 函数名:ESP8266_Net_Mode_Choose * 描述 :选择WF-ESP8266模块的工作模式 * 输入 :enumMode,工作模式 * 返回 : 1,选择成功 * 0,选择失败 * 调用 :被外部调用 */bool ESP8266_Net_Mode_Choose ( ENUM_Net_ModeTypeDef enumMode ){ switch ( enumMode ) { case STA: return ESP8266_Cmd ( "AT+CWMODE=1", "OK", "no change", 2500 ); case AP: return ESP8266_Cmd ( "AT+CWMODE=2", "OK", "no change", 2500 ); case STA_AP: return ESP8266_Cmd ( "AT+CWMODE=3", "OK", "no change", 2500 ); default: return false; }}对函数进行的时候,可以线在while中调用at测试函数,这样,看看是否成功。/* * 函数名:ESP8266_AT_Test * 描述 :对WF-ESP8266模块进行AT测试启动 * 输入 :无 * 返回 : 无 * 调用 :被外部调用 */void ESP8266_AT_Test ( void ){ ESP8266_RST_HIGH_LEVEL(); Delay_ms ( 1000 ); while ( ! ESP8266_Cmd ( "AT", "OK", NULL, 200 ) ) ESP8266_Rst (); }/* * 函数名:ESP8266_Rst * 描述 :重启WF-ESP8266模块 * 输入 :无 * 返回 : 无 * 调用 :被ESP8266_AT_Test调用 */void ESP8266_Rst ( void ){ #if 0 ESP8266_Cmd ( "AT+RST", "OK", "ready", 2500 ); #else ESP8266_RST_LOW_LEVEL(); Delay_ms ( 500 ); ESP8266_RST_HIGH_LEVEL(); #endif}/* * 函数名:ESP8266_Choose * 描述 :使能/禁用WF-ESP8266模块 * 输入 :enumChoose = ENABLE,使能模块 * enumChoose = DISABLE,禁用模块 * 返回 : 无 * 调用 :被外部调用 */void ESP8266_Choose ( FunctionalState enumChoose ){ if ( enumChoose == ENABLE ) ESP8266_CH_HIGH_LEVEL(); else ESP8266_CH_LOW_LEVEL();}
11,在main函数里面调用,
WiFi_Config();
/** * @brief WiFi_Config wifi 初始化 * @param 无 * @retval 无 */void WiFi_Config( void ){ WiFi_RST_INIT(); WiFi_led_INIT(); WiFi_USART1_INIT(); WiFi_USART2_INIT(); WiFi_NVIC_INIT();}
12,这儿特别注意,因为涉及到串口等模块,所以在STM32f10x_conf.h里面一定要添加自己需要的头文件。
这儿我吧我的所有的都拷贝下来了,读者根据自己的需要自己修改。
/* Includes ------------------------------------------------------------------*//* Uncomment/Comment the line below to enable/disable peripheral header file inclusion *///#include "stm32f10x_adc.h"//#include "stm32f10x_bkp.h"//#include "stm32f10x_can.h"//#include "stm32f10x_cec.h"//#include "stm32f10x_crc.h"//#include "stm32f10x_dac.h"//#include "stm32f10x_dbgmcu.h"#include "stm32f10x_dma.h"//#include "stm32f10x_exti.h"//#include "stm32f10x_flash.h"#include "stm32f10x_fsmc.h"#include "stm32f10x_gpio.h"//#include "stm32f10x_i2c.h"//#include "stm32f10x_iwdg.h"//#include "stm32f10x_pwr.h"#include "stm32f10x_rcc.h"//#include "stm32f10x_rtc.h"//#include "stm32f10x_sdio.h"#include "stm32f10x_spi.h"#include "stm32f10x_tim.h"#include "stm32f10x_usart.h"//#include "stm32f10x_wwdg.h"#include "misc.h" /* High level functions for NVIC and SysTick (add-on to CMSIS functions) */
具体的主函数我就不写了,每个人的需求不一样,很多东西都会不一样的,这儿我写下了大部分通用的,记得当时我学stm32和esp8266的时候,刚好是为了比赛,时间很紧张,信号有51单片机基础,然后之前一直在学c,java,android,java ee,(大学主要时间花在学习java和android上面),一直对软件很感兴趣,所以有编程的基础,所以学习stm32的时候,只花了很短的时间。网卡这块加上整合以前的代码rfid,和其他串口连接zigbee模块,一共花了10天时间。,庆幸与网络下帮助我解决了很多的错误问题,让我没有走太多的弯路,所以,今天分享一下当时我的路线,希望能帮助其他人。
http://download.csdn.net/album/detail/2287
http://download.csdn.net/album/detail/2287
http://download.csdn.net/album/detail/2287
http://download.csdn.net/album/detail/2287
下载地址
http://download.csdn.net/detail/xs15073722800/9187723
http://download.csdn.net/detail/xs15073722800/9187787
http://download.csdn.net/detail/xs15073722800/9187833
等等。。。方便你下载资料。
- stm32和esp8266程序资料分析
- ESP8266新手入门------百家长,附带STM32程序等
- 基于STM32和ESP8266的低成本物联网控制盒子
- esp8266的STM32驱动
- ESP8266资料整理
- STM32 wifi(ESP8266)模块实验
- STM32自动完成esp8266配置
- STM32资料
- STM32资料
- 基于stm32和ESP8266实现wifi模块smartlink功能以及TCP连接
- 基于uCOS-II系统使用STM32和Esp8266对接Yeelink物联网平台的Demo
- ESP8266程序烧写
- esp8266音频方案分析
- STM32学习笔记:ESP8266模块(1)
- ESP8266和MQTT
- STM32基础知识3-STM32串口USART1的使用方法和程序
- STM32基础知识3-STM32串口USART1的使用方法和程序
- ESP8266--学习笔记(转载资料一)
- apk更新、下载、安装(四)---DownloadManager ui方式
- windbg 符号文件设置路径
- AngularJS Documents 官方英文文档
- 多线程操作UI控件——DataGridView假死现象
- android 取消AsyncTask继续运行的解决方案
- stm32和esp8266程序资料分析
- Webview和Html5的交互
- ucenter 整合代码
- 竞聘演讲的技巧
- 调整eclipse或sts类存大小
- 我的OpenCV学习笔记(六):使用支持向量机(SVM)
- awk内建变量示范详解之NR、FNR、NF
- CUDA入门(1):环境配置与代码高亮显示
- matlab排列组合