本帖最后由 wenyangzeng 于 2016-12-16 16:23 编辑 / }# y( }, v9 s6 E$ I. M4 [ 1、简介 随着互联网技术的飞速发展,Wifi无线数据传输技术也随之不断发展成熟。而采用意法半导体的STM32系列单片机应用在Wifi无线数据传输中,能发挥STM32单片机的优异性能、缩短开发周期、产生较好的经济效益。 2、主要功能: 根据wifi信号传输的特点,由1台STM32单片机开发板工作在AP模式,作为服务器使用,其余STM32开发板工作在STA模式,做客户端使用。单片机之间的数据交换采用Wifi无线通讯来进行。可以应用在楼宇消防报警,也可以应用在无公害种植基地的温度、湿度的分散采集传输、集中监控等。优点是通讯无需敷设电缆,降低了项目投资成本,且作为数据采集的客户机,完全可以根据实际应用的要求将整个PCB板制作成mini结构,更方便现场安装。缺点是不适合较长距离通讯。 3、实施方案: / d; @) d0 L, X9 A+ Z(1)AP主机: 用1块开发板配置服务器TCP SERVER,用多台开发板配置客户机 TCP CLIENT,原则上所有开发板硬件配置都相同,都可以选用STM32F072 Nucleo开发板或其他的STM系列机型,本方案中在作为服务器的开发板上还配置了320*240图形点阵的液晶模块,用来显示工作状态和传输信息内容。我在上一贴使用的STM32F072 Nucleo开发板实验用的320*240液晶屏未拆除,刚好利用成为临时终端显示使用。(图1) * O9 z3 r% p5 @6 e* ] 图1 STM32F072 Nucleo开发板 (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接法相同 # }+ P$ Q& D) Z+ O+ y (6)对ESP8266的编程和通讯协议: 对ESP8266的 编程操作是使用发送AT指令来实现的,在KEIL5环境下的串口发送用printf()函数很方便。每次对ESP8266发送1条指令后ESP8266都要返回一段数据以供用户判断发送成功与否及命令执行情况如何。这里串口接收数据采用中断方式接收,减少数据接收的错误率。由于接收的数据不定长,采用数据指针累加、延时判断接收标志位等方法来确定一次通讯过程的结束。USART与ESP8266通讯协议为波特率9600,8位数据位,1位停止位,无奇偶校验。有的ESP8266通讯波特率是115200,只要修改一下即可。 : a! V0 N1 s. M ?5 P 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 , ~7 c: l5 Z! Y; n1 u 在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发送时的闪烁。 5 V' J0 _5 ~: b# m# ^. r: M3 ]: g- v 7 H) @% s) G) Y; ~. j8 s |
基于STM32F0的FOC5.2库PMSM驱动:程序+原理图+BOM等全部开源分享
【MCU实战经验】+STM32F030的步进电机加减速
STM32固件库分享,超全系列整理
【管管推荐】STM32经验分享篇
三创电子(Tcreate)-STM32F030核心板代码
STM32F0 ADC(DMA中断)多通道,注释超详细
FreeRTOS在STM32F030上的移植
基于STM32移植而引发的疑问经验分享
分享STM32F051中文参考手册(重制书签版)
游名:STM32F0+Trinamic智能步进驱动芯片TMC5160(最高20A)参考原...
2 K9 k7 s9 t- ?1 T
上个视频8 v% X1 c, B' r7 B0 I" U
一手操作一手摄像,图像摇晃,对不起。8 Z; P3 {- w9 F k1 p, Y
https://v.youku.com/v_show/id_XODY3MDkwODMy.html: ], C1 Q" y* _* m V
" ~! s+ a, T4 e1 f! z
因为我使用的液晶模块估计与大家使用的不兼容,代码就不全部放上,只放关键代码了。
客户端:1 O6 d" {: z1 T: K2 M7 {
#define ADC1_DR_Address ((uint32_t)0x4001244C)
ADC_InitTypeDef ADC_InitStructure;* c( k6 C' z* w' o# I% P
DMA_InitTypeDef DMA_InitStructure;7 Q' U) X; _8 H" Q+ K
__IO uint16_t ADCConvertedValue;9 Q6 b* y4 c- e; e" @% s
__IO uint16_t Rx_count=0;
__IO uint8_t Uart_buf[100];. S* }/ h- B: z) h) Q% g' m/ n- O
uint32_t tmp;
char TempSensor[10];
char const *ptr ;; Q9 s6 f2 v( h i" v" p ^0 Q
uint8_t Flag = 0x00;1 e& E- f- C' w7 q4 N" j
void echo(uint8_t Number);
void RCC_Configuration(void); u) h4 w" s/ L* H
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;' d( O. @, w3 R" U8 I4 b
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;- w6 r& D v, {! @* @' u
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;. z# _# _5 |) Q4 [
DMA_InitStructure.DMA_Priority = DMA_Priority_High;+ k/ r) Q7 Q3 Q& ~5 y4 Z
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;5 P- q, V& R/ {7 W |) e
DMA_Init(DMA1_Channel1, &DMA_InitStructure);* _% t5 V R, C2 D- R; i! O' s
DMA_Cmd(DMA1_Channel1, ENABLE);0 Q7 U2 G4 N' U9 \0 a
}' Z3 O8 G9 _) S& I# w
, ]1 Y' W7 q+ ^" v4 J
void ADC_Configuration(void)
{
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;4 Y( P4 X- @! |) V9 x" r; x1 D
ADC_InitStructure.ADC_ScanConvMode = ENABLE;; c+ [" A8 g: N
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;5 {) k/ f: [* w0 O! D6 _
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;7 X/ V* p, v7 l, F) v9 p$ O
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;1 ], c1 h( r$ n
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);2 ^9 } u8 `1 `4 x
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_55Cycles5);
ADC_TempSensorVrefintCmd(ENABLE);
ADC_DMACmd(ADC1, ENABLE);
ADC_Cmd(ADC1, ENABLE);+ p6 ~4 p8 d4 n8 `) l
ADC_ResetCalibration(ADC1);8 v: ^: k1 j, o0 u; x
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);! t7 Y$ \" K+ M: c4 V* i
while(ADC_GetCalibrationStatus(ADC1));
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}8 |2 N9 A3 R( N X8 l* r
int main(void)5 D* d. u, H5 C4 F
{uint8_t i=0;
ADC_Config();( X% t0 w) Z: }% l! f
DMA_Config();8 u, H+ M4 N: E* {8 U( q8 q1 ~
Uart_Init();
Nvic_Init();
for(i=0;i<100;i++)Uart_buf='\0';
USART_ClearFlag(USART1, USART_FLAG_RXNE);
Rx_count=0;" k3 W r0 N" F0 J
printf("AT+RST\r\n"); //重新启动
echo(0);
delay_ms(200);
printf("AT+CWMODE=1\r\n"); //模式1
echo(1);
delay_ms(200);& w( s+ r! l* J, b( X$ w
printf("AT+RST\r\n"); //重新启动" H+ L8 l4 A* F g6 ?
echo(0);5 k6 S5 q. x1 [- f/ v
delay_ms(500);3 h8 `; z3 {- |$ X
ptr = ( char const *)&(CWJAP);//AT+CWSAP="NUCLEO072","0123456789"% Y) E6 M$ ^& v# M& J% v
printf(ptr);: A+ y2 ]! d% ]# g' l$ y2 {
delay_ms(500);
echo(2);% B' L3 [7 O& T
printf("AT+CIPMUX=1\r\n"); //开启多连接* D j+ E. @, ?( I1 i
delay_ms(500); + a) c# R2 {3 t! q* S
echo(3);
delay_ms(200);( w; x- P5 B. I P. i) j& }: t
ptr = ( char const *)&(CIPSTART);* L, p- `" k6 A+ r% f, Q+ ^
printf(ptr);9 l5 z T s ~
delay_ms(500);, \; R) L+ f* J }' o: v6 V+ _3 @1 {
echo(4);
TempSensor_BCD();
ptr=( char *)&(TempSensor); 8 J8 [4 x% S+ }* E# i
printf("AT+CIPSEND=0,10\r\n");
printf(ptr);
echo(5);( o' |, V& o' U! w- c' ~- A( m
while (1)
{! y: N8 j0 b, E. V8 V K
while((DMA_GetFlagStatus(DMA1_FLAG_TC1)) == RESET );
DMA_ClearFlag(DMA1_FLAG_TC1);
delay_ms(100);0 k4 I4 P/ L: c. K
TempSensor_BCD();8 Q9 w4 N: J; z
ptr=( char *)&(TempSensor); ! Q# y. A6 e: i
printf("AT+CIPSEND=0,10\r\n");
printf(ptr);6 u+ q1 |: H x% x, N, p4 e# h
echo(5);
}" h. ?: B1 Q. Y/ b
}. T' e( y1 O+ y' E1 k' {6 n
服务器端
void Uart_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;% I0 `/ V* U' W! ], L
USART_InitTypeDef USART_InitStructure;
$ p" X' U7 r9 ~4 X. [$ n
RCC_AHBPeriphClockCmd( RCC_AHBPeriph_GPIOA , ENABLE); // 使能GPIOA端口
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); // 使能串口1时钟
. Y: G" |- h/ w! M$ A
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9, GPIO_AF_1);8 J, E: S) j e0 V2 r/ f
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;2 v) }$ h) e% T) Q/ G
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; }2 x! {0 ?* p
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; ; ^( x; a& O3 G' E( F) p
GPIO_Init(GPIOA , &GPIO_InitStructure);: }. L# \7 v5 o: @
7 \, d# b- Z2 M
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; & |9 e! u; T/ L$ a% C
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure); //串口配置1 D0 C- _! i# v
USART_ITConfig(USART1, USART_IT_RXNE,ENABLE);//打开中断 ! i9 P2 k5 y( \/ J0 F L9 d
USART_Cmd(USART1, ENABLE);//使能串口1
USART_ClearFlag(USART1, USART_FLAG_TC); & X" C7 z Q+ C
9 V1 b7 V$ v7 U! h4 E3 S
}
void Uart_Put_Char(unsigned char c)" o3 g+ {/ p, ~3 s4 V
{ , ~6 ^/ z9 ]$ H/ s% i
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1,c); / r3 y3 y6 a( o
}
unsigned char Uart_Get_Char(void)
{
unsigned char temp;
while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);
temp = (unsigned char)(USART_ReceiveData(USART1));! y, Q* L5 A6 B. {* @3 ]! }" Z2 p
return(temp);
}' r$ l7 ^( N# U: ~! ]# ]
int fputc(int ch, FILE *f)
{
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1,(uint8_t)ch);
return (ch);; ?; b* \: A7 B
}
void Nvic_Init(void)" L$ l- j8 m) h+ P8 O1 z) E. d, A
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;/ |6 F+ U# J1 ?( M8 N
NVIC_InitStructure.NVIC_IRQChannelPriority = 0x00;6 a. E6 j0 K5 g
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;, W( M; s; H5 F, }4 [: M
NVIC_Init(&NVIC_InitStructure);' Y% ~. m2 Y. ~& S4 N& Y8 g
}
GPIO_InitTypeDef GPIO_InitStructure; : g' ?- l: s# T6 w( l
void GPIO_Configuration(void)
{9 ]% q# U4 k/ O" Y% q
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/ Z" t5 C+ S3 \1 l& O: |% s
|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8;& _; [4 O0 ^' m3 J% o1 b0 d0 X
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;) u/ w i5 M& a
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; I* @: |, X, `. s" T3 e: q6 r! Q! b$ n: t
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; e0 H9 \3 [( L% U: D* R j6 k# s
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;7 M1 G7 s9 _- W2 z' j, I
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;7 N5 Z" [8 O' { j* k4 v5 O4 t' }
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;2 g" S! I j( l" Q4 A
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_5;& p" I5 X o6 p1 o% s
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;' s% _- I# `4 ]0 o$ Q. t
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOB, &GPIO_InitStructure);) ` p' }0 [3 s \
GPIOB->BSRR = GPIO_Pin_5;
}
int main(void)/ \) V- z- u7 f- _9 j: Q. X) n& p2 F+ ~
{ uint8_t i;
char const *ch;9 o" B( F3 I) H! ~+ Q) B
SystemInit();: k( _8 Z; {0 m- d4 _( ]! f
Nvic_Init();; M1 x: k8 o: t* r+ ^' Z8 _
GPIO_Configuration(); # ?1 Q+ `4 ]# m f& i7 X& z
LED_Init();' T+ ~: ]. e7 `
Uart_Init();
lcd_init();( U( O5 g+ K2 q$ U# Q( A
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);4 T4 B+ E- T$ [# `1 S
printf("AT+CIPMUX=1\r\n"); //开启多连接
echo(0);9 ~% d i3 U$ C3 l
printf("AT+CIPSERVER=1,8080\r\n"); //开启服务器模式8 F7 [4 r0 V' y
echo(0);
printf("AT+CIFSR\r\n"); //返回模块地址0 ]" ^8 i, `9 u) l, U; y
echo(0);7 @9 v" A' @# N6 j5 n
while(1)
{
if(Flag==1)
echo(1);# s z9 ]- z" q" d/ w1 Y
}, K1 Q% J: v* `# I) t- |0 ~
}
/ ^* K4 D) ]: ]! E z8 F
耗电不小,发射时要几百毫安的。
我也觉得是,呵呵
而且速率那么低的情况可以考虑zigbee做,传输距离更远