本帖最后由 wenyangzeng 于 2016-12-16 16:23 编辑 6 l. h! j ^: @# K: c" p 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) 5 }. x: R4 Q& S3 N$ G) @, I 图1 STM32F072 Nucleo开发板 # U) K0 q% Q& g (2)客户端机: 手头1块STM32F103C8-PKT用来配置成客户端使用,板上有一个电位器原设计连接STM32F103C8的ACD通道1,刚好用来采集数据。PA9和PA10经过跳线与232转换芯片连接,取下跳线刚好供ESP8266的URXD、UTXD连接。见图2。 在实际应用设计中当然还应当添加按键、蜂鸣器报警等外设。 图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稳压来供电。 图3 两片ESP8266接法相同 ) R' l: S# A8 z& Q/ G/ _) {0 b+ y (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”则表示服务器端已经配置成功。 F& f# E. w9 U' `# j4 d; q: r 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发送时的闪烁。 ) @# u5 _6 @: N6 S- q8 i0 B |
STM32固件库分享,超全系列整理
三创电子(Tcreate)-STM32F030核心板代码
STM32F0 ADC(DMA中断)多通道,注释超详细
FreeRTOS在STM32F030上的移植
基于STM32移植而引发的疑问经验分享
分享STM32F051中文参考手册(重制书签版)
游名:STM32F0+Trinamic智能步进驱动芯片TMC5160(最高20A)参考原...
【MCU实战经验】+STM32F030的步进电机加减速
STM32F0的中文技术参考手册(标签处理过)
基于STM32F030硬件SPI经验分享
6 i. v. g0 l/ D$ d- r+ I
上个视频
一手操作一手摄像,图像摇晃,对不起。
: O0 h6 W+ V0 l6 m
https://v.youku.com/v_show/id_XODY3MDkwODMy.html
+ p3 t- i3 C( _5 x) H5 I
因为我使用的液晶模块估计与大家使用的不兼容,代码就不全部放上,只放关键代码了。: W8 _! w. M7 f0 k) Z5 b
客户端:
#define ADC1_DR_Address ((uint32_t)0x4001244C). V9 ^( n& |! ^9 z9 d$ k( N7 @
ADC_InitTypeDef ADC_InitStructure;# @+ F2 O& q" f% p( K
DMA_InitTypeDef DMA_InitStructure;
__IO uint16_t ADCConvertedValue;
__IO uint16_t Rx_count=0;6 }" T6 ?' t2 P# }! p
__IO uint8_t Uart_buf[100];
uint32_t tmp;8 [( S+ C: L* r0 U
char TempSensor[10];$ z' U% I; {$ E. ?, Y2 a F
char const *ptr ;
uint8_t Flag = 0x00;
void echo(uint8_t Number);
void RCC_Configuration(void);
void GPIO_Configuration(void);$ V7 A: K' _2 L! ^4 @
void DMA_Configuration(void)
{ ) @+ v" q/ R; I. w
DMA_DeInit(DMA1_Channel1);) O* X" [# L7 P- |: [: e
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADCConvertedValue;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;# V; J6 y+ q; A6 i1 x2 o6 Y
DMA_InitStructure.DMA_BufferSize = 1;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;3 a" i* r# U- O+ o
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;" p5 g7 F( t% A
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;+ d- S5 y5 B1 M, f9 b) @: z7 X
DMA_InitStructure.DMA_Priority = DMA_Priority_High;" P1 I/ i Q! V1 H! \: f- }; A" J
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
DMA_Cmd(DMA1_Channel1, ENABLE);
}
6 O" {+ }9 P5 s
void ADC_Configuration(void)
{
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;# A- E/ T4 y, P( D* _% h: b
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;4 D1 H9 R# @6 O j! e/ O/ i
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;" z5 K; r! d: S! q H6 {- ]* {; l
ADC_Init(ADC1, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_55Cycles5);4 f9 a6 }# y, I
ADC_TempSensorVrefintCmd(ENABLE);
ADC_DMACmd(ADC1, ENABLE);
ADC_Cmd(ADC1, ENABLE);5 F% G$ T5 I: [& Z
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1); u6 _& A# [! C/ n+ a
while(ADC_GetCalibrationStatus(ADC1));& s% q0 U- u1 \' ^& g
ADC_SoftwareStartConvCmd(ADC1, ENABLE);4 s2 k1 U' j) m
}
int main(void)
{uint8_t i=0;
ADC_Config();& r: b4 Z: ]* {1 Y; U. z
DMA_Config();8 Z5 e9 U; ~! K6 J* m: B2 L
Uart_Init();+ S0 J9 z* E* V9 R3 h) o$ ~
Nvic_Init();5 i5 U1 y; F$ c0 p# V5 b9 M
for(i=0;i<100;i++)Uart_buf='\0';6 s& ]: F) P5 C, c2 C) S8 H% [
USART_ClearFlag(USART1, USART_FLAG_RXNE);5 l, v! U! T- J- t9 x6 S
Rx_count=0;( X Y8 r5 w E% @6 U
printf("AT+RST\r\n"); //重新启动
echo(0);
delay_ms(200);8 f! E0 C$ v X# z
printf("AT+CWMODE=1\r\n"); //模式1
echo(1);4 _+ @' h9 O* g/ i- u9 B
delay_ms(200);
printf("AT+RST\r\n"); //重新启动8 a! W' W) N/ U9 s7 d3 k
echo(0);
delay_ms(500);
ptr = ( char const *)&(CWJAP);//AT+CWSAP="NUCLEO072","0123456789"
printf(ptr);
delay_ms(500);* ]) P8 g7 V- |* {# }
echo(2);
printf("AT+CIPMUX=1\r\n"); //开启多连接" H9 n1 t7 O( n0 ]/ A6 y
delay_ms(500);
echo(3);
delay_ms(200);
ptr = ( char const *)&(CIPSTART);* X4 z, H& ~# I1 ^9 j
printf(ptr);. \! A0 W5 M" {/ Q0 ]/ r
delay_ms(500);+ d# r; E3 A% r
echo(4);
TempSensor_BCD();1 {7 ]* }/ ^3 I! ]* ? h# H7 R
ptr=( char *)&(TempSensor);
printf("AT+CIPSEND=0,10\r\n");0 l' F# w, Y ?# i2 a2 H
printf(ptr);+ A2 X3 f9 M% L* o, o6 b5 h
echo(5);
while (1)7 t. `( `% t# E h: R
{. g+ v5 n1 z( t9 @& _6 j( I& W) {% @
while((DMA_GetFlagStatus(DMA1_FLAG_TC1)) == RESET );
DMA_ClearFlag(DMA1_FLAG_TC1);/ i" D# r: o# D
delay_ms(100);. A) P0 w+ z% r2 X) G
TempSensor_BCD();. E6 ?( i* s0 H K( U0 ^+ P* V
ptr=( char *)&(TempSensor);
printf("AT+CIPSEND=0,10\r\n");% C) @" y8 h/ S/ W2 C$ P$ V
printf(ptr);% Y% O7 C9 w& n: Z9 m Y% u
echo(5);) N. s3 f/ e, m& P; Q
}
}) b1 y0 r! C/ h! J
服务器端8 Y8 X- p" J. `( t# i0 l; P/ G
void Uart_Init(void)
{! ~& t( k1 |" w3 ^9 G& h- ?" ^
GPIO_InitTypeDef GPIO_InitStructure;" C/ g0 c3 X& ^5 E' H
USART_InitTypeDef USART_InitStructure;
8 B! C. x- |$ y5 k; N7 n0 z# p
RCC_AHBPeriphClockCmd( RCC_AHBPeriph_GPIOA , ENABLE); // 使能GPIOA端口) N% x& {1 s$ P+ m! E. p
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); // 使能串口1时钟2 C- a, J& n7 S' J% I0 z$ r
. o+ L4 ?" l" W% c+ {
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9, GPIO_AF_1);- H, F7 R8 k; y4 F! @: z
GPIO_PinAFConfig(GPIOA ,GPIO_PinSource10, GPIO_AF_1); & n# z+ H2 c8 Y/ [7 ~1 h
% x) E: _4 l. V6 a
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;. `3 W+ X) y2 ~( t* o
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;7 p4 m4 t4 G+ j. N# Q* o! k) H6 m
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;4 Q0 s3 \! w# e3 D: r
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;! E+ U4 B/ F+ X
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; / `, w8 Y- G% M
GPIO_Init(GPIOA , &GPIO_InitStructure);* t4 E3 X* O; G o# e9 B( `$ P' g
) `) X2 `2 G9 c' C2 `
USART_InitStructure.USART_BaudRate = 9600; 4 ?* N% D0 B" m' E9 X- Z8 ~
USART_InitStructure.USART_WordLength = USART_WordLength_8b; 1 r5 f+ k+ A6 z1 S7 O* V& Z6 F! p
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No; - ~% V- r2 X& d9 s
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;# U# U0 S, h; W: _ E
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure); //串口配置/ T( m# C" L4 {" [
USART_ITConfig(USART1, USART_IT_RXNE,ENABLE);//打开中断 " ~* l8 ^9 b& ?- H
USART_Cmd(USART1, ENABLE);//使能串口1
USART_ClearFlag(USART1, USART_FLAG_TC);
) x8 `' s1 a( q
}
void Uart_Put_Char(unsigned char c): _% Z- P( `5 @* R9 A2 I9 L# f9 e% q
{ - U/ ^0 @; a4 { v: \1 `
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1,c); ; }4 d9 s1 r6 K9 I
}
; @, ^ X/ Q/ a" c1 Q A, i
unsigned char Uart_Get_Char(void)4 V; R8 L3 h( }* k3 m
{ - f# Q+ x) J6 c# @6 A+ V
unsigned char temp;
while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);
temp = (unsigned char)(USART_ReceiveData(USART1));% }2 H7 X8 l% w" O1 j
return(temp);
}
int fputc(int ch, FILE *f)
{
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);, t1 L) `; [' T; v
USART_SendData(USART1,(uint8_t)ch);
return (ch);
}
void Nvic_Init(void)) D7 a. l; K: ^9 X- a' x) v' _5 M
{4 G$ z/ D; L N& q9 E
NVIC_InitTypeDef NVIC_InitStructure;& M. `* ~) ]! d' X" W+ ]: z
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 0x00;" F4 E. b6 y8 R$ Q8 X
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);$ D- a! S, s D, e5 d" u
}
GPIO_InitTypeDef GPIO_InitStructure; ; l! `3 V& [2 S, ?' x* ]1 r
void GPIO_Configuration(void)! V3 K7 w3 N l' x
{
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;2 i) a* R" d N2 j' V
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;+ v5 }8 k0 Z0 _* Z
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;9 W. z' c9 e& G9 Z8 Z
GPIO_Init(GPIOC, &GPIO_InitStructure);) t1 p) ?* F4 O# K; ?2 f- }
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;$ V$ G1 I* e# e6 C+ K
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;, [6 G" H' _3 J% k0 @7 K
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);( X* D( w9 r- |2 t% A
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;( \" d7 r# I' G! [; V3 [& W: \$ e5 \
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;. s. E" a. ^4 n1 M: C
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;! p; f7 W9 N( Z/ s0 }
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIOB->BSRR = GPIO_Pin_5;% A8 N# r) d* J3 l" `, z! a
}
int main(void)
{ uint8_t i;
char const *ch;
SystemInit();8 Q% P' q6 s( ~) w5 c
Nvic_Init();( T" e' K/ P5 y. m& A/ ]& h+ {4 m
GPIO_Configuration(); ) C0 C2 Z$ J N; J. f% }( g
LED_Init();6 W, W! @$ @$ M8 l5 ^( v1 X/ r
Uart_Init();
lcd_init();
lcd_clr();* }0 r6 l3 Y$ ?- c% N, H
Screen();
for(i=0;i<100;i++)Uart_buf='\0';
USART_ClearFlag(USART1, USART_FLAG_RXNE);( l1 {+ Q7 ]7 h5 T
Rx_count=0;1 T8 L# ^& L, R: D; I f- J
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);) i. g! a A( U+ F0 {4 a& W& K
printf("AT+CIPSERVER=1,8080\r\n"); //开启服务器模式+ P' T# t9 F8 e. P) ^
echo(0);
printf("AT+CIFSR\r\n"); //返回模块地址, v5 j3 [, x0 z6 G/ }
echo(0);
while(1); y6 t9 u# Q1 J& R
{
if(Flag==1) & N/ o: c L, W$ h* ]
echo(1);2 @2 d5 [3 M/ [: M/ V" B4 |
}. ^7 r) q* y2 D' u
}3 {$ o$ y' Q" ~: q. o) a9 ~
耗电不小,发射时要几百毫安的。
我也觉得是,呵呵
而且速率那么低的情况可以考虑zigbee做,传输距离更远