目录
前言
一.WIFI模块
二、串口中断
1.初始化GPIO和中断
2.定义串口收发函数
3.定义串口收发函数
4.定义中断函数?
总结
前言
上文主要针对项目电源这一块做了记录,涉及到开关电源与串联型电源电路的设计与器件选型,本文将接着对于功能实现部分之STM串口与wifi模块连接并进行发送与接收进行记录。主要是代码的实现部分。
一.WIFI模块
ATK-ESP8266是ALIENTEK推出的一款高性能的UART-WiFi(串口-无线)模块,ATK-ESP8266模块采用串口(LVTTL)与MCU(或其他串口设备)通信,内置TCP/IP协议栈,能够实现串口与WIFI之间的转换。通过ATK-ESP8266模块,传统的串口设备只是需要简单的串口配置,即可通过网络(WIFI)传输自己的数据,ATK-ESP8266模块支持LVTTL串口,兼容3.3V和5V单片机系统。模块支持串口转WIFI STA、串口转AP和WIFI STA+WIFI AP的模式。
硬件连接较为简单,如图与单片机连接即可,因为功能实现为串口2与wifi模块连接与串口1实现,C8T6的串口2收发为PA2/PA3,且共地一共连接。
ATK_ESP8266 模块支持 STA/AP/STA+AP 三种工作模式:1)STA 模式: ESP8266 模块通过路由器连接互联网,手机或电脑通过互联网实现对设备的远程控制;2)AP 模式: 默认模式 ATK_ESP8266 模块作为热点,实现手机或电脑直接与模块通信,实现局域网无线控制;3)STA+AP 模式:两种模式的共存模式, (STA 模式) 即可以通过路由器连接到互联网,并通过互联网控制设备;(AP 模式)也可作为 wifi 热点,其他 wifi 设备连接到模块。这样实现局域网和广域网的无缝切换,方便操作。项目利用的是ATK_ESP8266 模块作为 server,需建立多连接,即可以连接多个 client以下为 ATK_ESP8266 作为 STA 模式建立 TCP SERVER 的设置,结合数据手册构建函数:
void wifi()
{
send_via_uart2((char*)"AT+CWMODE=1"); //设置SAT模式
delay_ms(1000);
send_via_uart2((char*)"AT+RST");
delay_s(2);
send_via_uart2((char*)"AT+CWJAP=\"WiFi_id\",\"WiFi_passport\""); //连接路由器
delay_s(3);
send_via_uart2((char*)"AT+CIPMUX=1"); //启动多链接
delay_s(2);
send_via_uart2((char*)"AT+CIPSERVER=1,889"); //建立 server 设置端口号
delay_s(2);
send_via_uart2((char*)"AT+CIFSR"); //获取模块 IP 地址 结果返回OK IP/MAC地址
}
电脑或者手机连接到 server,电脑或手机作为 client,串口助手虚拟一个客户端,连接成功就能发送数据。
二、串口中断
1.初始化GPIO和中断
首先头文件中初始化串口1,串口2
void uart1_int(u32 bt)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// 打开串口GPIO的时钟
RCC_APB2PeriphClockCmd((RCC_APB2Periph_GPIOA), ENABLE);
// 打开串口外设的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
// // 将USART Tx的GPIO配置为推挽复用模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// // 将USART Rx的GPIO配置为浮空输入模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 配置串口的工作参数
// 配置波特率为bt
USART_InitStructure.USART_BaudRate = bt;
// 配置 针数据字长
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);
// // 串口中断优先级配置
// NVIC_Configuration(); //原本有的 只是我自己没配置
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //子优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure);
// // 使能串口接收中断
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //使能或者失能指定的USART中断 接收中断
// USART_ClearFlag(USART1,USART_FLAG_TC); //清楚待处理的标志位??
// // 使能串口
USART_Cmd(USART1, ENABLE);
}
/***串口2初始化**/
void uart2_int(u32 bt)
{
GPIO_InitTypeDef GPIO_InitStructure; //声明结构体变量用来初始化GPIO
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// 打开串口GPIO的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// 打开串口外设的时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
// // 将USART Tx的GPIO配置为推挽复用模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// // 将USART Rx的GPIO配置为浮空输入模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 配置串口的工作参数
// 配置波特率为bt
USART_InitStructure.USART_BaudRate = bt;
// 配置 针数据字长
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(USART2, &USART_InitStructure);
// 串口中断优先级配置
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// // 使能串口接收中断
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); //使能或者失能指定的USART中断 接收中断
// // 使能串口
USART_Cmd(USART2, ENABLE);
}
2.定义串口收发函数
代码如下(示例):
void send_via_uart1(char *p)
{
u8 i=0;
u8 j=0;
char *temp=p;
while(*temp !='\0')
{
j++;
temp++;
}
while(i<j)
{
USART1 ->DR=p[i];
delay_ms(5);//延时防止丢掉第一个数
while((USART1 ->SR&0X40)==0);//等待发送结束
i++;
}
USART1->DR=0x0D;
while((USART1 ->SR&0x40)==0); //等待发送结束
USART1->DR=0x0A;
while((USART1 ->SR&0x40)==0); //等待发送结束
}
void send_via_uart2(char *p)
{
u8 i=0;
u8 j=0;
char *temp=p;
while(*temp !='\0')
{
j++;
temp++;
}
while(i<j)
{
USART2 ->DR=p[i];
delay_ms(5);//延时防止丢掉第一个数
while((USART2 ->SR&0X40)==0);//等待发送结束
i++;
}
USART2->DR=0x0D;
while((USART2 ->SR&0x40)==0); //等待发送结束
USART2->DR=0x0A;
while((USART2 ->SR&0x40)==0); //等待发送结束
}
3.定义串口收发函数
串口收发函数实现通过串口
void send_via_uart1(char *p)
{
u8 i=0;
u8 j=0;
char *temp=p;
while(*temp !='\0')
{
j++;
temp++;
}
while(i<j)
{
USART1 ->DR=p[i];
delay_ms(5);//延时防止丢掉第一个数
while((USART1 ->SR&0X40)==0);//等待发送结束
i++;
}
USART1->DR=0x0D;
while((USART1 ->SR&0x40)==0); //等待发送结束
USART1->DR=0x0A;
while((USART1 ->SR&0x40)==0); //等待发送结束
}
void send_via_uart2(char *p)
{
u8 i=0;
u8 j=0;
char *temp=p;
while(*temp !='\0')
{
j++;
temp++;
}
while(i<j)
{
USART2 ->DR=p[i];
delay_ms(5);//延时防止丢掉第一个数
while((USART2 ->SR&0X40)==0);//等待发送结束
i++;
}
USART2->DR=0x0D;
while((USART2 ->SR&0x40)==0); //等待发送结束
USART2->DR=0x0A;
while((USART2 ->SR&0x40)==0); //等待发送结束
}
4.定义中断函数?
实现串口1接收 串口1发送 串口2中断接收发送给串口1互传数据:
void USART1_IRQHandler(void)
{
u8 ucTemp;
if(USART_GetFlagStatus(USART1,USART_IT_RXNE) != RESET)
{
ucTemp=USART_ReceiveData(USART1);
USART_SendData(USART1,ucTemp); //识别中断标志位,将串口1接收到的数据发给串口1
}
}
void USART2_IRQHandler(void) //串口2接收到wifi模块发送过来的命令 给串口1发过去
{
uint8_t ucTemp;
if(USART_GetITStatus(USART2,USART_IT_RXNE)!=RESET)
{
ucTemp = USART_ReceiveData(USART2);
USART_SendData(USART1,ucTemp); //将串口2的数据发给串口2
start_flag=1; //发送标志位置一
}
}
最后在主函数里面初始化串口,设置好波特率,定义一个发送标志位,在
#include "stm32f10x.h"
#include "my_usart.h"
int main()
{
u8 send_flag=0;
u8 u1_num;
u8 data1[256];
u8 k=0;
u8 t;
u32 len;
char s[] = "\n";
char rec_cmd[100];
/*初始化USART 配置模式为 115200,中断接收*/
uart1_int(115200);
uart2_int(115200);
wifi();
send_via_uart2((char*)"wifi模块命令已设置");
while(1)
{
if(start_flag==1)
{
send_via_uart2( s); //串口2发送字符串数组
while(data1[k]!=0)
{
USART_SendData(USART2,data1[k]); //将data的数据发送出去给串口2
while((USART2->SR&0x40)==0); //判断串口2是否发送结束
data1[k]=0; //对数组清零
k++; //data数组里面的一个一个发出去,角标加一
}
u1_num=0;
start_flag=0; //串口2发送结束后标志位清零
k=0;
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); //关闭串口发送非空中断
}
}
}
总结
要点:初始化要连接的GPIO;初始化EXTI用于产生中断/事件;初始化NVIC,用于处理中断;编写中断函数。
|