
本帖最后由 wenyangzeng 于 2016-12-16 16:23 编辑 % Z3 |. }( d( Q9 n' w) K. F# H 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) ![]() 图1 STM32F072 Nucleo开发板 * ~* k& ]3 x6 R6 s4 q: `+ _# l (2)客户端机: 手头1块STM32F103C8-PKT用来配置成客户端使用,板上有一个电位器原设计连接STM32F103C8的ACD通道1,刚好用来采集数据。PA9和PA10经过跳线与232转换芯片连接,取下跳线刚好供ESP8266的URXD、UTXD连接。见图2。 在实际应用设计中当然还应当添加按键、蜂鸣器报警等外设。 $ l6 p+ W* }/ ^. ]/ B ![]() 图2 STM32F103C8-PKT开发板 7 c- N, |$ W$ g (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稳压来供电。 ![]() 图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 ; N4 B2 t# l) K% ~* \5 T7 Z 在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发送时的闪烁。 ! Q7 s8 [* X- w3 S2 ?( O% ]0 h * c" h# C$ C& _( j |
STM32的启动模式配置与应用
STM32F030C8T6+DRV8701+磁隔离大功率直流电机驱动器制作
STM32固件库分享,超全系列整理
STM32F0F1F4内部flash擦写时间和寿命
游名:STM32F030+FT1610FF1高精度超声波测距模块测距教程及参...
分享STM32F051中文参考手册(重制书签版)
STM32F0 IIC slave mode
三创电子(Tcreate)-STM32F030调试之I2C篇
基于STM32F0的FOC5.2库PMSM驱动:程序+原理图+BOM等全部开源分享
【MCU实战经验】+STM32F030的步进电机加减速
. d/ T! g/ m h
上个视频/ g- c) a4 V( |1 ]$ ~ L
一手操作一手摄像,图像摇晃,对不起。: Q, l o: x, Q$ Q) S
9 \6 e! n$ s$ H* N! X
https://v.youku.com/v_show/id_XODY3MDkwODMy.html* r. ~* t7 I) M: u
因为我使用的液晶模块估计与大家使用的不兼容,代码就不全部放上,只放关键代码了。
客户端:
#define ADC1_DR_Address ((uint32_t)0x4001244C)
ADC_InitTypeDef ADC_InitStructure;* f0 T7 R, x/ E' p( z- J- c
DMA_InitTypeDef DMA_InitStructure;/ [8 F, I( V. q0 z" C
__IO uint16_t ADCConvertedValue;6 z( L2 n( M3 N- L" r
__IO uint16_t Rx_count=0;
__IO uint8_t Uart_buf[100];8 W6 ]$ v/ r7 D; Z$ ?- Q. L
uint32_t tmp; p- B* o+ ~- v5 H; C1 V2 ]
char TempSensor[10];
char const *ptr ;3 c& |9 s8 d/ G `& d- ~: C( a% n
uint8_t Flag = 0x00;
void echo(uint8_t Number);% F, A% K( B- x" O& q" x% j
void RCC_Configuration(void);( F C# m; M% ~5 V9 f0 h- W
void GPIO_Configuration(void);' g/ N2 G. t& C0 Z( @/ l# i
/ |' v$ m3 }; ~4 [
void DMA_Configuration(void)
{
DMA_DeInit(DMA1_Channel1);- A \% g1 m) R' n
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;% n. W1 S* F! q
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;/ a3 ^8 W' T, }# E3 G, i
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;0 o) O1 A' i# ^, c
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;+ w8 S- Y4 I4 ]
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;' S! ]" x" `. v) M. x* ^
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);' V& [& F7 F* H# d2 S
DMA_Cmd(DMA1_Channel1, ENABLE);- G% L0 j8 {5 T3 W
}& s9 ]& |3 @' `- |6 G
void ADC_Configuration(void)7 f+ g+ Z# M2 C* ], F0 x
{
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = ENABLE;9 h* W0 m/ ~+ `6 b; c7 u
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;* C5 ?. W1 }* T0 ~1 s3 l
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;- u5 Y7 e8 U, ~- b
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;1 O% {$ \- y0 Q! } E- C2 U
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);1 M! A2 a- K4 M- [. H; L
ADC_Cmd(ADC1, ENABLE);
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));# T0 b- L- C( `8 f0 `- B$ t
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}; K, ~; P7 ^3 q: b( c
int main(void)
{uint8_t i=0;
ADC_Config();
DMA_Config();
Uart_Init();
Nvic_Init();! L4 S8 a7 B; x
for(i=0;i<100;i++)Uart_buf='\0';$ S1 r, ?) `; ^" ?8 j- Y
USART_ClearFlag(USART1, USART_FLAG_RXNE);# C# W$ |5 m: v: z' Y$ ?6 J
Rx_count=0; @9 F( B4 T1 I# F
printf("AT+RST\r\n"); //重新启动# E% I" D1 A+ j# f3 l. q J
echo(0);
delay_ms(200);) @; G8 Y5 n) i) O& ?+ k
printf("AT+CWMODE=1\r\n"); //模式12 r/ D4 S5 ?& r
echo(1);
delay_ms(200);
printf("AT+RST\r\n"); //重新启动
echo(0);! i& p/ o% Q1 b# p; W( ?
delay_ms(500);
ptr = ( char const *)&(CWJAP);//AT+CWSAP="NUCLEO072","0123456789"
printf(ptr);* @1 a. m+ R5 a" F' c+ ]# R
delay_ms(500);
echo(2);
printf("AT+CIPMUX=1\r\n"); //开启多连接; Z$ D. s8 j& _3 g
delay_ms(500); 6 E# l) `# z; I# P, f
echo(3);
delay_ms(200);
ptr = ( char const *)&(CIPSTART);2 a( o7 J- \5 Z" S Q
printf(ptr);; x% P. ]# r' A& P- k
delay_ms(500);- ~9 c* Z! z2 N* Y& s$ z9 e# X5 f
echo(4);
TempSensor_BCD();
ptr=( char *)&(TempSensor);
printf("AT+CIPSEND=0,10\r\n");
printf(ptr);3 X' b* `) @2 B0 T) L
echo(5);
while (1)0 d( c/ A! m: I/ p, ~6 m
{+ T$ |% U' I" c) R* ~
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);, B& z) q! t" J& _' `5 ~. X& W
echo(5);
}
}
服务器端0 W. |3 i* { c
void Uart_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;- j1 ?$ Q) U* R, J n
USART_InitTypeDef USART_InitStructure;
RCC_AHBPeriphClockCmd( RCC_AHBPeriph_GPIOA , ENABLE); // 使能GPIOA端口; {& }: s+ W' \( @6 B$ u. S
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); // 使能串口1时钟
. C0 t( _5 Y- [
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9, GPIO_AF_1);3 n9 Y5 [, ?* h9 F! V
GPIO_PinAFConfig(GPIOA ,GPIO_PinSource10, GPIO_AF_1);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 ; 3 `+ q( ]0 ]" @/ h
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;- Q0 Q8 @' e4 b3 E% v9 _
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;* c5 S$ n, B8 s( N6 g7 R. g) U; l( o
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;) U% B6 N9 b/ n$ L2 b
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;" E" o. D- R9 p8 ?& S5 P
GPIO_Init(GPIOA, &GPIO_InitStructure);. f( ~( m2 O6 B' Z+ c" W4 `9 b
6 d8 ^+ ^* M5 X6 ^; f5 ]
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;) ]4 U6 g3 m( y1 c2 I% T, F
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; - Z1 Z8 |; }8 F9 B
GPIO_Init(GPIOA , &GPIO_InitStructure);
; y1 }$ }/ s( x( }& G! F
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; 6 w& n/ A. O C' [
USART_Init(USART1, &USART_InitStructure); //串口配置
USART_ITConfig(USART1, USART_IT_RXNE,ENABLE);//打开中断
USART_Cmd(USART1, ENABLE);//使能串口1
USART_ClearFlag(USART1, USART_FLAG_TC);
+ G( w N9 L; P, {
}# ]8 S+ Q: F! J! @$ ]+ |$ ^' b
void Uart_Put_Char(unsigned char c)5 D6 g" y5 v- @1 z% w
{
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1,c); - V$ y: i4 F' j2 }, D0 `) @
}( i$ z" P' o8 \! p& Z& m! ]8 p# u" Q) h
2 G* X$ L; A& H% K$ r+ O& U
unsigned char Uart_Get_Char(void)
{ / B! [ v. X8 Z. x. _7 M( J9 D
unsigned char temp;% S3 S' H% ^ O, N: b
while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);
temp = (unsigned char)(USART_ReceiveData(USART1));: D: _2 |: u/ Z0 H R
return(temp);
}
int fputc(int ch, FILE *f)3 y6 A1 Z* D/ y& ^5 g7 M W8 c
{
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);! Z+ ^8 G% W3 k# u, f: V) d
USART_SendData(USART1,(uint8_t)ch);
return (ch);4 @# `! t2 q: v! [
}
void Nvic_Init(void)- h" j8 |! C: \7 j: Z
{
NVIC_InitTypeDef NVIC_InitStructure;- R' {9 H Z+ ~; B- ]
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);* M. @+ ?+ q+ O$ B6 V$ U9 B
}( X. o9 t" d {+ M
GPIO_InitTypeDef GPIO_InitStructure; % [, I3 z6 a9 l4 c
void GPIO_Configuration(void)% R* |% D: w, C& a: s
{
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;5 Z( k4 C8 N# ?3 ?
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;& } ~% z& ?& M9 Z1 k' h
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; R# G, o7 h$ E- B& ^
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;6 _0 Z r& D6 @' }' e2 m9 ~
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);+ D1 {- i; `5 M# O/ F X ?3 A
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_5;! O; g4 N) @: k& A
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;9 |9 ~- M; N" {6 K, Y
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIOB->BSRR = GPIO_Pin_5;2 _) e/ S W* c& C( H2 Y
}+ Y) q, H$ a; n& S) Z6 _1 Z; j
int main(void)
{ uint8_t i; ! {( X G, u' K
char const *ch;0 G4 [8 j7 N2 f4 \! u5 U
SystemInit();
Nvic_Init();
GPIO_Configuration();
LED_Init();) [0 A6 K/ H( Y6 S
Uart_Init();1 [2 y2 C/ ]; p" I! j' b* C$ g
lcd_init(); o$ v7 u# v& H, X
lcd_clr();1 Y. L" A* I/ V
Screen();& K& u( ]9 z* o) N+ Z& q
for(i=0;i<100;i++)Uart_buf='\0';& n7 Q" L' x$ Q2 j; L
USART_ClearFlag(USART1, USART_FLAG_RXNE);8 O. A$ T3 H1 J8 ?5 B
Rx_count=0;
printf("AT+RST\r\n"); //重新启动. V+ ?: k5 K8 V+ n8 O
echo(0);1 v# y( j a9 s+ i
printf("AT+CWMODE=2\r\n"); //AP模式% k: v8 Q; @) I& I! K1 j
echo(0);' s6 c% U- t5 W" g6 z- L
ch = ( char const *)&(CWSAP);//AT+CWSAP="NUCLEO072","0123456789",11,0 ,通道号11
printf(ch);. k3 ^6 t: C1 Q7 K( h' J
echo(0);
printf("AT+CIPMUX=1\r\n"); //开启多连接
echo(0);& {$ f: F' c q, a
printf("AT+CIPSERVER=1,8080\r\n"); //开启服务器模式
echo(0);% {0 S1 Q% c4 L( z2 r3 e
printf("AT+CIFSR\r\n"); //返回模块地址
echo(0);
while(1)" i( x6 m0 {- V i; G
{
if(Flag==1)
echo(1);
}' Z0 B9 s; A0 ]' ~4 H
}
4 B! T+ M/ N6 k3 @; z- _& ]8 b
6 k9 |7 q1 L& r2 I& t7 L: `' a, x
耗电不小,发射时要几百毫安的。
我也觉得是,呵呵
而且速率那么低的情况可以考虑zigbee做,传输距离更远