你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

基于STM32F072 Nucleo的Wifi无线数据传输 精华  

[复制链接]
wenyangzeng 发布时间:2015-1-7 21:51
本帖最后由 wenyangzeng 于 2016-12-16 16:23 编辑

     1、简介
       随着互联网技术的飞速发展,Wifi无线数据传输技术也随之不断发展成熟。而采用意法半导体的STM32系列单片机应用在Wifi无线数据传输中,能发挥STM32单片机的优异性能、缩短开发周期、产生较好的经济效益。
2、主要功能
根据wifi信号传输的特点,由1台STM32单片机开发板工作在AP模式,作为服务器使用,其余STM32开发板工作在STA模式,做客户端使用。单片机之间的数据交换采用Wifi无线通讯来进行。可以应用在楼宇消防报警,也可以应用在无公害种植基地的温度、湿度的分散采集传输、集中监控等。优点是通讯无需敷设电缆,降低了项目投资成本,且作为数据采集的客户机,完全可以根据实际应用的要求将整个PCB板制作成mini结构,更方便现场安装。缺点是不适合较长距离通讯。
3、实施方案

(1)AP主机:
    用1块开发板配置服务器TCP SERVER,用多台开发板配置客户机 TCP CLIENT,原则上所有开发板硬件配置都相同,都可以选用STM32F072 Nucleo开发板或其他的STM系列机型,本方案中在作为服务器的开发板上还配置了320*240图形点阵的液晶模块,用来显示工作状态和传输信息内容。我在上一贴使用的STM32F072 Nucleo开发板实验用的320*240液晶屏未拆除,刚好利用成为临时终端显示使用。(图1)

服务器.jpg
                           图1  STM32F072 Nucleo开发板

     (2)客户端机
      手头1块STM32F103C8-PKT用来配置成客户端使用,板上有一个电位器原设计连接STM32F103C8的ACD通道1,刚好用来采集数据。PA9和PA10经过跳线与232转换芯片连接,取下跳线刚好供ESP8266的URXD、UTXD连接。见图2。
       在实际应用设计中当然还应当添加按键、蜂鸣器报警等外设。

客户机.jpg
                          图2 STM32F103C8-PKT开发板

     (3)无线Wifi模块:
    选用现成ESP8266模块,简单方便。  ESP8266的URXD、UTXD连接PA9、PA10,5V供电接U5V。
      (4)ESP8266的连接方法
      对ESP8266模块的操作控制使用串口通讯方式,连接方法见图3,ESP8266的URXD分别接STM32F072RB和STM32F103C8的PA9(TXD), UTXD分别接STM32F072RB和STM32F103C8的PA10(RXD),
  (5)供电:
      由于ESP8266工作电流较大,直接从开发板+3.3V引出无法正常工作,所以要分别用1只AMS1117从USB5V提供3.3V稳压来供电。
接线图.JPG
    图3 两片ESP8266接法相同

    (6)对ESP8266的编程和通讯协议
          对ESP8266的 编程操作是使用发送AT指令来实现的,在KEIL5环境下的串口发送用printf()函数很方便。每次对ESP8266发送1条指令后ESP8266都要返回一段数据以供用户判断发送成功与否及命令执行情况如何。这里串口接收数据采用中断方式接收,减少数据接收的错误率。由于接收的数据不定长,采用数据指针累加、延时判断接收标志位等方法来确定一次通讯过程的结束。USART与ESP8266通讯协议为波特率9600,8位数据位,1位停止位,无奇偶校验。有的ESP8266通讯波特率是115200,只要修改一下即可。

    STM32F072 Nucleo开发板配置成服务器端,工作模式为AP模式(模式2)。具体过程如下:
1、 重启模块:           发送 AT+RST
2、 设置工作模式:  发送 AT+CWMODE=2
3、 再次重启模块:     发送 AT+RST
4、 设置服务器参数:发送 AT+CWSAP="NUCLEO072","0123456789",11,0
5、 开启多连接:      发送 AT+CIPMUX=1
6、 开启服务器模式:发送 AT+CIPSERVER=1,8080
7、 返回模块地址:   发送 AT+CIFSR

    在STM32F072 Nucleo开发板的液晶屏幕上我将上述指令返回信息显示在屏幕上,当第7条指令返回信息:“192.168.4.1   OK”则表示服务器端已经配置成功。

   STM32F103C8-PKT开发板配置成客户端:STA(模式1)
1、 重启模块:           发送 AT+RST
2、 设置工作模式:   发送 AT+CWMODE=1
3、 再次重启模块:     发送  AT+RST
4、 连接网络:         发送  AT+CWSAP="NUCLEO072","0123456789"(这个参数就是服务器端设置的参数)
5、 开启多连接:      发送  AT+CIPMUX=1
6、 建立连接:         发送:AT+CIPSTART=0,"TCP","192.168.4.1",8080 (这个参数就是服务器端第6和第7条指令的参数)
   连接成功后,就可以从客户端发送数据到服务器了:AT+CIPSEND=0,10后随10个数据在TempSensor[]数组中。
这10个数据是客户端ADC转换结果换算成电压值并转换成ASCII码,因为定长10位,不足部分补上空格。此处ACD转换采用DMA传输,省却了涉及对ADC转换操作的过程。
    调试工作应该先调好服务器端,再调试客户端。由于每次代码修改都要重新启动AT指令,因此本例程的调试是一个痛苦漫长的等待过程,您就慢慢去体会吧!
   在随后视频中你可以看到接收端的Wifi板上的蓝色LED响应了发送端Wifi板上蓝色LED发送时的闪烁。



评分

参与人数 1 ST金币 +20 收起 理由
zero99 + 20

查看全部评分

收藏 1 评论49 发布时间:2015-1-7 21:51

举报

49个回答
wenyangzeng 最优答案 回答时间:2015-1-8 13:42:35
本帖最后由 wenyangzeng 于 2015-7-31 22:31 编辑

上个视频
一手操作一手摄像,图像摇晃,对不起。

https://v.youku.com/v_show/id_XODY3MDkwODMy.html


wenyangzeng 回答时间:2015-1-7 21:51:32
本帖最后由 wenyangzeng 于 2015-1-19 11:54 编辑

  因为我使用的液晶模块估计与大家使用的不兼容,代码就不全部放上,只放关键代码了。
客户端:
#define ADC1_DR_Address    ((uint32_t)0x4001244C)
ADC_InitTypeDef ADC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
__IO uint16_t ADCConvertedValue;
__IO uint16_t Rx_count=0;
__IO uint8_t Uart_buf[100];
uint32_t tmp;
char TempSensor[10];
char const *ptr             ;
uint8_t Flag = 0x00;
void echo(uint8_t Number);
void RCC_Configuration(void);
void GPIO_Configuration(void);

void DMA_Configuration(void)
{   
  DMA_DeInit(DMA1_Channel1);
  DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADCConvertedValue;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
  DMA_InitStructure.DMA_BufferSize = 1;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  DMA_Init(DMA1_Channel1, &DMA_InitStructure);
  DMA_Cmd(DMA1_Channel1, ENABLE);
}

void ADC_Configuration(void)
{
  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
  ADC_InitStructure.ADC_ScanConvMode = ENABLE;
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfChannel = 1;
  ADC_Init(ADC1, &ADC_InitStructure);
  ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_55Cycles5);
  ADC_TempSensorVrefintCmd(ENABLE);
  ADC_DMACmd(ADC1, ENABLE);
  ADC_Cmd(ADC1, ENABLE);
  ADC_ResetCalibration(ADC1);
  while(ADC_GetResetCalibrationStatus(ADC1));
  ADC_StartCalibration(ADC1);
  while(ADC_GetCalibrationStatus(ADC1));
  ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}
int main(void)
{uint8_t i=0;
  ADC_Config();
   DMA_Config();
Uart_Init();
   Nvic_Init();
       for(i=0;i<100;i++)Uart_buf='\0';
       USART_ClearFlag(USART1, USART_FLAG_RXNE);
        Rx_count=0;
        printf("AT+RST\r\n");           //重新启动
         echo(0);
       delay_ms(200);
        printf("AT+CWMODE=1\r\n");     //模式1
        echo(1);
       delay_ms(200);
        printf("AT+RST\r\n");           //重新启动
        echo(0);
        delay_ms(500);
         ptr = ( char const *)&(CWJAP);//AT+CWSAP="NUCLEO072","0123456789"
              printf(ptr);
         delay_ms(500);
              echo(2);
       printf("AT+CIPMUX=1\r\n");                                   //开启多连接
       delay_ms(500);     
       echo(3);
       delay_ms(200);
       ptr = ( char const *)&(CIPSTART);
       printf(ptr);
       delay_ms(500);
       echo(4);
       TempSensor_BCD();
        ptr=( char  *)&(TempSensor);         
        printf("AT+CIPSEND=0,10\r\n");
        printf(ptr);
         echo(5);
  while (1)
       {
    while((DMA_GetFlagStatus(DMA1_FLAG_TC1)) == RESET );
    DMA_ClearFlag(DMA1_FLAG_TC1);
     delay_ms(100);
     TempSensor_BCD();
      ptr=( char  *)&(TempSensor);         
       printf("AT+CIPSEND=0,10\r\n");
       printf(ptr);
        echo(5);
  }
}
服务器端
void Uart_Init(void)
{
        GPIO_InitTypeDef  GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;
                  
        RCC_AHBPeriphClockCmd( RCC_AHBPeriph_GPIOA   , ENABLE);   // 使能GPIOA端口
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);             // 使能串口1时钟
         
        GPIO_PinAFConfig(GPIOA,GPIO_PinSource9, GPIO_AF_1);
        GPIO_PinAFConfig(GPIOA ,GPIO_PinSource10, GPIO_AF_1);                          

        GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_9 ;                 
        GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_10;
             GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
        GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;      
        GPIO_Init(GPIOA , &GPIO_InitStructure);

        USART_InitStructure.USART_BaudRate = 9600;                                    
        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(USART1, &USART_InitStructure);        //串口配置
      
        USART_ITConfig(USART1, USART_IT_RXNE,ENABLE);//打开中断   
        USART_Cmd(USART1, ENABLE);//使能串口1
        USART_ClearFlag(USART1, USART_FLAG_TC);
      
}
void Uart_Put_Char(unsigned char c)
{   
  while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);  
USART_SendData(USART1,c);  
}

unsigned char Uart_Get_Char(void)
{   
     unsigned char temp;
     while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);
     temp = (unsigned char)(USART_ReceiveData(USART1));
     return(temp);   
}
int fputc(int ch, FILE *f)
{
  while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
  USART_SendData(USART1,(uint8_t)ch);
  return (ch);
}
void Nvic_Init(void)
{
  NVIC_InitTypeDef  NVIC_InitStructure;
  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPriority = 0x00;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}

GPIO_InitTypeDef GPIO_InitStructure;     
void GPIO_Configuration(void)
{

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA|RCC_AHBPeriph_GPIOB|RCC_AHBPeriph_GPIOC, ENABLE);
       GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3
                          |GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
      GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
       GPIO_Init(GPIOC, &GPIO_InitStructure);
       GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
      GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
       GPIO_Init(GPIOA, &GPIO_InitStructure);
     GPIO_InitStructure.GPIO_Pin =        GPIO_Pin_3|GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
      GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
     GPIO_Init(GPIOB, &GPIO_InitStructure);
       GPIOB->BSRR = GPIO_Pin_5;
}
int main(void)
{ uint8_t i;      
  char const *ch;
  SystemInit();
  Nvic_Init();
  GPIO_Configuration();
  LED_Init();
  Uart_Init();
  lcd_init();
  lcd_clr();
   Screen();
       for(i=0;i<100;i++)Uart_buf='\0';
        USART_ClearFlag(USART1, USART_FLAG_RXNE);
    Rx_count=0;
    printf("AT+RST\r\n");           //重新启动
    echo(0);
     printf("AT+CWMODE=2\r\n");     //AP模式
     echo(0);
       ch = ( char const *)&(CWSAP);//AT+CWSAP="NUCLEO072","0123456789",11,0  ,通道号11
       printf(ch);
       echo(0);
       printf("AT+CIPMUX=1\r\n");                                   //开启多连接
       echo(0);
       printf("AT+CIPSERVER=1,8080\r\n"); //开启服务器模式
       echo(0);
       printf("AT+CIFSR\r\n");        //返回模块地址
       echo(0);
  while(1)
       {
              if(Flag==1)   
            echo(1);
  }
}



沐紫 回答时间:2015-1-7 22:09:07
不错哦,谢谢楼主
sacq12 回答时间:2015-1-7 23:02:56
在楼主这里,新认识了Wifi模块ESP8266。学习~
damiaa 回答时间:2015-1-8 15:55:57
好。支持
万里-363223 回答时间:2015-1-9 11:00:52
sacq12 发表于 2015-1-7 23:02
在楼主这里,新认识了Wifi模块ESP8266。学习~

我也觉得是,呵呵
沐紫 回答时间:2015-1-13 17:21:17
不错哦,加油
mlxy123xy 回答时间:2015-1-13 23:29:14
这个不错,,等额拿到新板子,和原来的discovery也来试试无线互联
slotg 回答时间:2015-1-14 01:18:11
不错的分享,我还不晓得有 ESP8266 这个模块可以用,长知识了。
12345下一页

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版