OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5823|回复: 3

我用UART5和WIFI通信,中间仿真时出现这个问题:

[复制链接]

29

主题

85

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
247
金钱
247
注册时间
2015-4-26
在线时间
5 小时
发表于 2015-5-7 22:25:30 | 显示全部楼层 |阅读模式
5金钱
uart5.c
#include "delay.h"
#include "uart5.h"
#include "stdarg.h"  
#include "stdio.h"  
#include "string.h"   

/*串口5驱动代码,库函数版本 */

//串口发送缓存区
__align(8) u8 UART5_TX_BUF[UART5_MAX_SEND_LEN]; //发送缓冲,最大UART5_MAX_SEND_LEN字节
#ifdef UART5_RX_EN   //如果使能了接收    
//串口接收缓存区
u8 UART5_RX_BUF[UART5_MAX_RECV_LEN]; //接收缓冲,最大UART5_MAX_RECV_LEN个字节.


//通过判断接收连续2个字符之间的时间差不大于10ms来决定是不是一次连续的数据.
//如果2个字符接收间隔超过10ms,则认为不是1次连续数据.也就是超过10ms没有接收到
//任何数据,则表示此次接收完毕.
//接收到的数据状态
//[15]:0,没有接收到数据;1,接收到了一批数据.
//[14:0]:接收到的数据长度
u16 UART5_RX_STA=0;
void UART5_IRQHandler(void)
{
u8 res;
if(USART_GetITStatus(UART5, USART_IT_RXNE) != RESET)//接收到数据,(接收到的数据必须是0x0d 0x0a结尾)
{
res =USART_ReceiveData(UART5);//读取到收到的数据
if(UART5_RX_STA<UART5_MAX_RECV_LEN) //还可以接收数据
{
TIM_SetCounter(TIM3,0);//计数器清空          
if(UART5_RX_STA==0)TIM3_Set(1); //使能定时器3的中断 
UART5_RX_BUF[UART5_RX_STA++]=res; //记录接收到的值  
}else 
{
UART5_RX_STA|=1<<15; //强制标记接收完成
}
}

//void UART5_IRQHandler(void)                 //串口5中断服务程序
//{
// u8 res;
//    if(USART_GetITStatus(UART5, USART_IT_TXE) != RESET)
//     {
//     USART_ClearITPendingBit(UART5, USART_IT_TXE); 
//     }

//     if(USART_GetITStatus(UART5, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
//     {
// res = USART_ReceiveData(UART5);//(UART5->DR); //读取接收到的数据
//  }
// }


//初始化IO PC10 PC11 串口4 
//pclk1CLK1时钟频率(Mhz)
//bound:波特率  
void UART5_Init(u32 bound)
{
//0.GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
USART_InitTypeDef UART_InitStructure;
//1.串口时钟使能,复用端口
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD,ENABLE); // GPIOC时钟 |RCC_APB2Periph_AFIO
//RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO ,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5,ENABLE);
//UART5_TX  C.12 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //PC.12
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOC, &GPIO_InitStructure); //初始化PC.12
//UART5_RX  D.2  
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;//PD.2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOD, &GPIO_InitStructure);  //初始化PD.2
//2.复位串口5
USART_DeInit(UART5); 
//3.串口参数初始化
//UART5->BRR=(36*1000000)/(bound);// 波特率设置
UART_InitStructure.USART_BaudRate = bound;
UART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
UART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
UART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
UART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
UART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式

//初始化串口 5
USART_Init(UART5, &UART_InitStructure); 
//使能串口
USART_Cmd(UART5, ENABLE); 
#ifdef UART5_RX_EN   //如果使能了接收
USART_ITConfig(UART5, USART_IT_RXNE, ENABLE);//若接收数据寄存器满,开启中断
NVIC_InitStructure.NVIC_IRQChannel = UART5_IRQn; 
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //子优先级0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
TIM3_Init(99,7199); //10ms中断
UART5_RX_STA=0; //清零
TIM3_Set(0); //关闭定时器4
#endif
}


//定时器4中断服务程序    
void TIM3_IRQHandler(void)
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)//是更新中断
{   
UART5_RX_STA|=1<<15; //标记接收完成
TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx更新中断标志    
TIM3_Set(0); //关闭TIM3  
}    
}
//设置TIM3的开关
//sta:0,关闭;1,开启;
void TIM3_Set(u8 sta)
{
if(sta)
{     
TIM_SetCounter(TIM3,0);//计数器清空
TIM_Cmd(TIM3, ENABLE);  //使能TIMx
}else TIM_Cmd(TIM3, DISABLE);//关闭定时器4   
}
//通用定时器中断初始化
//这里始终选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数  
void TIM3_Init(u16 arr,u16 psc)
{
NVIC_InitTypeDef NVIC_InitStructure;
TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能//TIM3时钟使能    
//定时器TIM3初始化
TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim ???
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
 
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断
 
// NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
// NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;//抢占优先级3
// NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //子优先级3
// NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
// NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
//
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

}
#endif
/**************************************************
  UART5发送一个字节
 **************************************************/
  void UART5_Tx_Char(u8 i)
  {
    USART_SendData(UART5,i); //发往WIFI模块 
while(USART_GetFlagStatus(UART5, USART_FLAG_TXE)==RESET); 
//printf("tset:\r\n%s\r\n",i);
  }  
  /*******************************************
  UART5发送字符串
  *******************************************/
  void UART5_Tx_Str(u8 *pt, u8 length)
  {    
u8 i;
for( i=0;i<length;i++ ){
UART5_Tx_Char(*pt++);
   }
   //delay_ms(10);
  }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ESP_01.c
#include "delay.h"  
#include "usart.h"  
#include "uart5.h"  
#include "ESP_01.h"  
#include "string.h"  
#include "math.h"

/*ESP_01 Wifi驱动代码*/

/********************************************************************************     
*功能:通过AT指令检测ESP_01Wifi模块是否已经连接 *
*初始化ESP_01模块 *
*返回值:0,成功;1,失败. *
********************************************************************************/
u8 ESP_01_Init(void)
{
u8 retry=10,t;    
u8 temp=1;
u8 len;
u8 reclen = 0;
u8 AT[] = "AT\r\n"; //+GMR
UART5_Init(9600);//初始化串口5为:115200,波特率.
while(retry--)
{
delay_ms(10);
/*发送AT测试指令到WIFI,查看是否接收OK*/
UART5_Tx_Str(AT, sizeof(AT)/sizeof(AT[0]));
for(t=0;t<10;t++) //最长等待50ms,来接收WIFI模块的回应
{
if(UART5_RX_STA&0X8000)
break;
delay_ms(5);
}
if(UART5_RX_STA&0x8000) //接收到一次数据了 
{
temp=UART5_RX_STA&0X7FFF; //得到数据长度 
/******************************test_uart4****************************/
len=UART5_RX_STA&0x3fff;//得到此次接收到的数据长度
reclen=UART5_RX_STA&0X7FFF; //得到数据长度
UART5_RX_BUF[reclen]=0; //加入结束符
printf("test2:%s\r\n",UART5_RX_BUF);//发送回应数据到串口1
/*********************************************************************/
UART5_RX_STA=0;
if((temp==0x0C)&&UART5_RX_BUF[7]=='O'&&UART5_RX_BUF[8]=='K')
{
temp=0;//接收到OK响应
break;
}
}    
}    
if(retry==0)temp=1; //检测失败
return temp;  
}  
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.c
#include "stm32f10x.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "uart4.h"
#include "uart5.h"
#include "led.h"
#include "spp_ca.h"
#include "ESP_01.h"
#include "string.h"

u32 i=0;     // 定义延时参量
int main(void)
{
u8 t;
u8 len;
u16 times=0;   
u8 reclen=0;  
SystemInit();  //系统时钟配置函数通过不同的定义 来选择不同的主频 这里设置是72m 
LED_Init(); //初始化与LED连接的硬件接口 
  delay_init(); //延时函数初始化
NVIC_Configuration();// 设置中断优先级分组
uart_init(9600); //串口初始化为9600

//while (SPP_CA_Init());//初始化蓝牙模块,先判断STM32和蓝牙是否连接上 
while (ESP_01_Init());//初始化WIFI模块,先判断STM32和WIFI是否连接上

while(1)
{
if(USART_RX_STA&0x8000)//通过USART1接收数据(即PC->USART1->UART5)
{
len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
printf("\r\nSend_data2:\r\n");
for(t=0;t<len;t++)
{
USART1->DR=USART_RX_BUF[t];
while((USART1->SR&0X40)==0);//等待发送结束
}
//UART5_Tx_Str(USART_RX_BUF, strlen(USART_RX_BUF));//发送--UART5--WIFI
UART5_Tx_Str(USART_RX_BUF, sizeof(USART_RX_BUF)/sizeof(USART_RX_BUF[0]));//发送--UART5--WIFI
/*最长等待500ms,来接收WIFI模块的回应 */
for(t=0;t<10;t++)
{
if(UART5_RX_STA&0X8000)break;
delay_ms(50);
}
for(t=0;t<len;t++) USART_RX_BUF[t] = 0;//这里USART1发到UART5上去后,500ms后就开始清零USART1
if(UART5_RX_STA&0x8000)//通过UART4接收数据
{
len=UART5_RX_STA&0x3fff;//得到此次接收到的数据长度
reclen=UART5_RX_STA&0X7FFF; //得到数据长度
UART5_RX_BUF[reclen]=0; //加入结束符
printf("\r\n%s\r\n",UART5_RX_BUF);//发送回应数据到串口1
UART5_RX_STA = 0;
delay_ms(500);
}
else
{
times++;
if(times%200==0)
printf("Wifi module data returned failure!\r\n"); 
}
USART_RX_STA=0;
}
}
return 0;

}

以上代码,在main.c里初始化while (ESP_01_Init())时,是AT指令,返回ok,且UART5_RX_STA仿真时,值为0x800c,(wifi被触发时送的),初始化没问题;

接下来while(1)里,用usart1通过PC发送到uart5中UART5_RX_STA的值是0x80c8(这是位什么)?










最佳答案

查看完整内容[请看2#楼]

回复【3楼】正点原子: --------------------------------- 原因找到了,过程:PC->USART1->UART5->WIFI PC->USART1,中断里有\r\n协议 UART5->WIFI有\r\n 但是USART1->UART5里却没有这个协议加上去就OK了
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

29

主题

85

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
247
金钱
247
注册时间
2015-4-26
在线时间
5 小时
 楼主| 发表于 2015-5-7 22:25:31 | 显示全部楼层
回复【3楼】正点原子:
---------------------------------
原因找到了,过程:PC->USART1->UART5->WIFI
PC->USART1,中断里有\r\n协议
UART5->WIFI有\r\n
但是USART1->UART5里却没有这个协议加上去就OK了
回复

使用道具 举报

29

主题

85

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
247
金钱
247
注册时间
2015-4-26
在线时间
5 小时
 楼主| 发表于 2015-5-7 22:40:23 | 显示全部楼层
以上代码,在main.c里初始化while (ESP_01_Init())时,是AT指令,返回ok,且UART5_RX_STA仿真时,值为0x800c(wifi被触发是发送的)初始化没问题;

但在下面while(1)里,通过PC发送到USART1-->UART5,中断触发时,UART5_RX_STA的值0x80cB,之后就死掉了
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165353
金钱
165353
注册时间
2010-12-1
在线时间
2108 小时
发表于 2015-5-8 00:18:24 | 显示全部楼层
仿真调试下,只能慢慢来
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-25 21:07

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表