|
本帖最后由 wenyangzeng 于 2016-12-16 16:23 编辑 " i, x" E6 ~7 F v 1、简介 随着互联网技术的飞速发展,Wifi无线数据传输技术也随之不断发展成熟。而采用意法半导体的STM32系列单片机应用在Wifi无线数据传输中,能发挥STM32单片机的优异性能、缩短开发周期、产生较好的经济效益。 2、主要功能: 根据wifi信号传输的特点,由1台STM32单片机开发板工作在AP模式,作为服务器使用,其余STM32开发板工作在STA模式,做客户端使用。单片机之间的数据交换采用Wifi无线通讯来进行。可以应用在楼宇消防报警,也可以应用在无公害种植基地的温度、湿度的分散采集传输、集中监控等。优点是通讯无需敷设电缆,降低了项目投资成本,且作为数据采集的客户机,完全可以根据实际应用的要求将整个PCB板制作成mini结构,更方便现场安装。缺点是不适合较长距离通讯。 3、实施方案: 2 c' l3 W F, N' o% V8 a(1)AP主机: 用1块开发板配置服务器TCP SERVER,用多台开发板配置客户机 TCP CLIENT,原则上所有开发板硬件配置都相同,都可以选用STM32F072 Nucleo开发板或其他的STM系列机型,本方案中在作为服务器的开发板上还配置了320*240图形点阵的液晶模块,用来显示工作状态和传输信息内容。我在上一贴使用的STM32F072 Nucleo开发板实验用的320*240液晶屏未拆除,刚好利用成为临时终端显示使用。(图1)
图1 STM32F072 Nucleo开发板 % j! g- K8 s3 Y# T$ d' n6 B8 W (2)客户端机: 手头1块STM32F103C8-PKT用来配置成客户端使用,板上有一个电位器原设计连接STM32F103C8的ACD通道1,刚好用来采集数据。PA9和PA10经过跳线与232转换芯片连接,取下跳线刚好供ESP8266的URXD、UTXD连接。见图2。 在实际应用设计中当然还应当添加按键、蜂鸣器报警等外设。 0 ~3 b' q v7 T! `' b+ F
图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接法相同 (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 6 G% R4 d4 E1 m* f# g7 g 在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发送时的闪烁。 ! l: l& t1 z- j8 ~; @4 X4 g 7 J8 E& }+ Q, S |
DMA 原理从 0 到 1:为什么它能解放 CPU?一文讲透 DMA 的工作流程
小白也能明白的STM32的低功耗与唤醒机制
STM32系统中2种数据掉电保护的方法
分享STM32F051中文参考手册(重制书签版)
AI工具训练营-用ChatGPT解决HID Keyboard实现的问题
STM32固件库分享,超全系列整理
STM32小白入门指南:从基础到OTA实现方案
STM32超详细学习笔记
新手必看!STM32单片机应该怎么学?
如果你解决了这些问题,就可以直接学STM32
微信公众号
手机版
; f5 w v# Y4 o4 r% _
上个视频
一手操作一手摄像,图像摇晃,对不起。+ D; Q' }+ {( T) m0 ]1 ^
https://v.youku.com/v_show/id_XODY3MDkwODMy.html- l3 E" C% y/ _, w
因为我使用的液晶模块估计与大家使用的不兼容,代码就不全部放上,只放关键代码了。4 U' x: B8 ~# }9 |" ]
客户端:
#define ADC1_DR_Address ((uint32_t)0x4001244C)" S( x) n( D. ^1 q1 G
ADC_InitTypeDef ADC_InitStructure; P5 m6 j: I( _$ ~7 y
DMA_InitTypeDef DMA_InitStructure;
__IO uint16_t ADCConvertedValue;* ~9 l c, \3 d0 u
__IO uint16_t Rx_count=0;
__IO uint8_t Uart_buf[100];
uint32_t tmp;
char TempSensor[10];5 l+ p; Z7 \! X% C
char const *ptr ;
uint8_t Flag = 0x00;2 _3 Y2 {& g3 R3 k* k
void echo(uint8_t Number);0 o8 P6 A. d- ]! l- E& ?
void RCC_Configuration(void);4 H7 ^0 Q+ u3 o/ d- j0 _
void GPIO_Configuration(void);
7 i2 x$ t+ O/ I+ g
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;# L& g, G# h- \/ d9 Y
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;! O6 I. r1 `1 Z: ?3 w! k+ m/ _
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;; b; K+ v. J5 Z( h
DMA_InitStructure.DMA_Priority = DMA_Priority_High;( z3 b3 Y/ _ N2 j
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
DMA_Cmd(DMA1_Channel1, ENABLE);# }6 Y. B* q3 }" l
}
, k5 B) ]2 }" u/ p* |; ]4 d
void ADC_Configuration(void)
{8 S% `. s8 |, {& B3 O: X
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;2 _, n9 _( h9 `6 u' ~
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;% V0 K# E9 n) J1 a
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_55Cycles5);( \! b u7 }9 Q" `
ADC_TempSensorVrefintCmd(ENABLE);% y0 w8 ?8 P8 c2 {1 V
ADC_DMACmd(ADC1, ENABLE);
ADC_Cmd(ADC1, ENABLE);( }) g5 m' k5 z+ m: b; b+ f& m! E0 f, a* m
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}1 X& ?+ D2 S5 |
int main(void)
{uint8_t i=0;+ K: D. T' I6 d. S
ADC_Config();2 C; l8 s5 ~# N/ P! N
DMA_Config();
Uart_Init();
Nvic_Init();2 m6 t% u/ Q' N" C$ T5 F
for(i=0;i<100;i++)Uart_buf='\0';( v! D% N0 q+ e" f# c9 k
USART_ClearFlag(USART1, USART_FLAG_RXNE);
Rx_count=0;- t& \& p* f; V# w/ W) |. W8 C9 t* Q8 j
printf("AT+RST\r\n"); //重新启动$ A$ F& f. v7 Z0 @6 O
echo(0);
delay_ms(200);9 p8 m1 E5 V; E! w5 F0 a) z/ ], R
printf("AT+CWMODE=1\r\n"); //模式1" z/ Y' T# h8 W8 a) G6 p/ n
echo(1);
delay_ms(200);
printf("AT+RST\r\n"); //重新启动
echo(0);% V# v, Q; L7 P5 L
delay_ms(500);9 m! Z7 ~6 l- l, N
ptr = ( char const *)&(CWJAP);//AT+CWSAP="NUCLEO072","0123456789"* g L' e! U& u9 c" r; n9 m0 R
printf(ptr);
delay_ms(500);
echo(2);5 ]6 n$ j3 f% _) k5 c" s
printf("AT+CIPMUX=1\r\n"); //开启多连接2 ^8 A0 X1 y, u; R4 c' M* {
delay_ms(500); Y3 |7 b7 d% f# t! X
echo(3);! A( U! y0 g1 E9 h+ q ?
delay_ms(200);+ j; E8 M' M4 ^; E, T
ptr = ( char const *)&(CIPSTART);5 k* u/ z3 h. r% ~
printf(ptr);
delay_ms(500);
echo(4);
TempSensor_BCD();/ B9 S/ N. T9 Y3 m& ?& P! A
ptr=( char *)&(TempSensor);
printf("AT+CIPSEND=0,10\r\n");6 ]9 V3 k- s3 T2 u4 z: d$ T5 O1 f
printf(ptr);, |$ R) D) r4 E
echo(5);) W- d5 y3 z8 C! ^; D7 {; E
while (1)& [/ G, \3 b- _
{
while((DMA_GetFlagStatus(DMA1_FLAG_TC1)) == RESET );- S- I- D! U( k. b
DMA_ClearFlag(DMA1_FLAG_TC1);2 z( [% ]0 l/ o1 }
delay_ms(100);$ I8 X. k8 s. ~7 k4 ~0 Y
TempSensor_BCD();
ptr=( char *)&(TempSensor); & v6 r# o! @7 o! W+ ?8 @
printf("AT+CIPSEND=0,10\r\n");
printf(ptr);
echo(5);/ N7 b! e9 Q6 a
}# t, Z, T+ w2 j- U! o0 t2 \
}
服务器端! r# h# E$ G5 Z! C) N; ~& y
void Uart_Init(void)# q" {4 e" r4 t1 J, e1 c I/ s* _
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
8 S3 n% j, T* f9 m
RCC_AHBPeriphClockCmd( RCC_AHBPeriph_GPIOA , ENABLE); // 使能GPIOA端口4 U/ b- `* C1 O* h+ O
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); // 使能串口1时钟
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9, GPIO_AF_1);
GPIO_PinAFConfig(GPIOA ,GPIO_PinSource10, GPIO_AF_1); 1 [4 |$ a/ s; m2 r K$ @1 G
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 ; 8 V; i4 R1 t' V- X5 ?- a2 o0 H& n
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;) m+ F; q+ A5 q; G
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;1 ^6 E P# w7 k; M
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;- u' ~- [( a Z3 v0 r& c8 A
GPIO_Init(GPIOA, &GPIO_InitStructure);; T! X/ f2 j* w
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;, S8 v" J6 }2 F) J) Q
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;4 z7 {+ |+ h, S' i W2 h
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA , &GPIO_InitStructure);& ]( ]" b. X4 T2 H4 `
USART_InitStructure.USART_BaudRate = 9600; $ y$ o! P( T5 P/ ]
USART_InitStructure.USART_WordLength = USART_WordLength_8b; 4 x3 |% H. M* P7 j
USART_InitStructure.USART_StopBits = USART_StopBits_1; " p6 c' L6 u, Q/ z& r
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); //串口配置2 x$ T$ l# |3 W) o2 i
USART_ITConfig(USART1, USART_IT_RXNE,ENABLE);//打开中断 Q# x8 o. i5 R, V$ I2 X$ N
USART_Cmd(USART1, ENABLE);//使能串口1; N5 \4 F/ k7 Z4 C9 i+ h+ O: B+ D9 Y% X
USART_ClearFlag(USART1, USART_FLAG_TC);
& ?' d" v9 @ C
}' C( \' i6 A. }6 t) x: l4 s
void Uart_Put_Char(unsigned char c)
{ 6 z4 @% |. `" z0 V
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1,c);
}2 n+ d* ?; `- [& N
, l3 f4 f0 b4 | x6 s
unsigned char Uart_Get_Char(void)* v9 q9 }. b9 L/ M! b3 ~/ f
{ / h, k+ }2 `) v# h0 S R
unsigned char temp;3 d% N* f! S" v& e2 J0 K' K
while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);
temp = (unsigned char)(USART_ReceiveData(USART1));6 ^% m0 |; E$ i5 d
return(temp); 1 G& Y5 s# M: t
}% c* W3 W2 X5 R) `9 o$ G& K6 r
int fputc(int ch, FILE *f). x3 G# `$ N' A* T8 g p7 k' _9 L
{. W, T1 E7 Y" P4 i' c0 E* o
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);1 V" [7 u5 p- X3 W1 ]9 ^
USART_SendData(USART1,(uint8_t)ch);
return (ch);
}
void Nvic_Init(void)
{* L5 c5 _8 K0 u/ g- r( t6 s5 I
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
+ H! q: k! |# h, e* U
GPIO_InitTypeDef GPIO_InitStructure;
void GPIO_Configuration(void)$ V' j2 A& m# d; e6 {* _) b+ M
{
8 @: H/ y' x+ d; d+ y/ o
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA|RCC_AHBPeriph_GPIOB|RCC_AHBPeriph_GPIOC, ENABLE);4 n) X3 \1 `( R8 n
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_39 q `2 r! { @% L, D7 Z. a6 s$ i. H
|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8;$ t0 N8 P0 `$ t
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;# q/ E8 Z* V# } m8 m: u6 o
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;1 L* @. {: A) T( G! B
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;4 w& o* x0 m! Q6 s0 d: w& ?
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;2 [8 _) e/ P* f+ {" { x4 i
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;4 i6 O! q. p) L- \3 }
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;- f4 E# ^7 C4 v9 A0 f4 V; i
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_5;# E8 K/ D/ X7 s1 `% z% ~
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;4 O* E7 ?* X; A) x
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;& M) F" Z) g; [( M
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; D9 a4 k2 U! }' p; J
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;0 m' Y. X$ X+ R2 z5 \, L
GPIO_Init(GPIOB, &GPIO_InitStructure);4 H4 w$ j& }5 o% Q/ X( @
GPIOB->BSRR = GPIO_Pin_5;3 W; j; ?- ^+ ?6 l
}8 E; S9 ~3 O; F* ]% U
int main(void). \/ |" D1 V" |5 J* m
{ uint8_t i; * D2 G; q( d0 T# N4 s0 y% [3 E) U
char const *ch;! j% d) w2 s L. }$ |9 p
SystemInit();! W4 ?4 p1 o$ `. K0 T+ P
Nvic_Init();' \/ o# U' A+ b% W* \ r
GPIO_Configuration();
LED_Init();# Q2 f" g7 \$ X- b+ }7 D6 m
Uart_Init();
lcd_init();
lcd_clr();! \7 m: l! v; G. [* I' b7 V0 G
Screen();/ c; u. l' |7 n4 N3 f# m7 y5 {
for(i=0;i<100;i++)Uart_buf='\0';, J" \6 R3 ~. E
USART_ClearFlag(USART1, USART_FLAG_RXNE);
Rx_count=0;
printf("AT+RST\r\n"); //重新启动$ c" \) A5 x" y. O5 m- b
echo(0);8 ~$ i/ S) p' u1 c( h$ A, w0 l7 O, `
printf("AT+CWMODE=2\r\n"); //AP模式; Q6 u5 ~- s, A5 O: V4 ~* i
echo(0);- K4 a7 J1 D( G3 Q/ i
ch = ( char const *)&(CWSAP);//AT+CWSAP="NUCLEO072","0123456789",11,0 ,通道号11! z9 H' w0 T A$ B
printf(ch);8 A( Z1 J6 a s1 A$ C
echo(0);# E2 f+ w9 X" |8 X& y
printf("AT+CIPMUX=1\r\n"); //开启多连接
echo(0);6 c2 u7 L! w: m* ]
printf("AT+CIPSERVER=1,8080\r\n"); //开启服务器模式: [% r9 B0 P, I1 u# [0 x
echo(0);
printf("AT+CIFSR\r\n"); //返回模块地址! g# K& R1 E1 u! g. k- A; ~
echo(0);
while(1)
{, o3 f$ a$ Q) c6 ?
if(Flag==1) 3 f* o4 ]5 w& t& o1 x
echo(1);, g5 s1 i2 _4 {
}
}% o3 w, W$ \ \1 k8 z
! ?2 \" I9 s1 T6 ~3 n
耗电不小,发射时要几百毫安的。
我也觉得是,呵呵
而且速率那么低的情况可以考虑zigbee做,传输距离更远