OpenEdv-开源电子网

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

这里的0x8000与0x3fff是指的什么吗?然后在分别与上USART_RX_STA的用处

[复制链接]

82

主题

194

帖子

0

精华

高级会员

Rank: 4

积分
596
金钱
596
注册时间
2015-10-16
在线时间
72 小时
发表于 2015-10-29 21:55:17 | 显示全部楼层 |阅读模式
5金钱
#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
//ALIENTEK战舰STM32开发板实验4
//串口实验  
//技术支持:www.openedv.com
//广州市星翼电子科技有限公司 
 int main(void)
 {
  u8 t;
u8 len;
u16 times=0;
delay_init();     //延时函数初始化  
NVIC_Configuration(); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
uart_init(9600); //串口初始化为9600
  LED_Init();     //LED端口初始化
KEY_Init();          //初始化与按键连接的硬件接口
  while(1)
{
if(USART_RX_STA&0x8000)
{   
len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
printf("\r\n您发送的消息为:\r\n\r\n");
for(t=0;t<len;t++)
{
USART_SendData(USART1, USART_RX_BUF[t]);//向串口1发送数据
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
}
printf("\r\n\r\n");//插入换行
USART_RX_STA=0;
}else
{
times++;
if(times%5000==0)
{
printf("\r\n战舰STM32开发板 串口实验\r\n");
printf("正点原子@ALIENTEK\r\n\r\n");
}
if(times%200==0)printf("请输入数据,以回车键结束\n");  
if(times%30==0)LED0=!LED0;//闪烁LED,提示系统正在运行.
delay_ms(10);   
}
}  
 }

最佳答案

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

USART_RX_STA与0X8000进行与运算,是用来判断是否接收到数据的,USART_RX_STA与0X3FFF进行与运算是用来确定接收到的数据长度的,USART_RX_STA的每个bit的含义教程里面有详细的讲解,就连代码中也有注释的啊
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

88

主题

7377

帖子

5

精华

资深版主

Rank: 8Rank: 8

积分
14980
金钱
14980
注册时间
2013-11-13
在线时间
1823 小时
发表于 2015-10-29 21:55:18 | 显示全部楼层
USART_RX_STA与0X8000进行与运算,是用来判断是否接收到数据的,USART_RX_STA与0X3FFF进行与运算是用来确定接收到的数据长度的,USART_RX_STA的每个bit的含义教程里面有详细的讲解,就连代码中也有注释的啊
开往春天的手扶拖拉机
回复

使用道具 举报

6

主题

115

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1027
金钱
1027
注册时间
2015-6-1
在线时间
126 小时
发表于 2015-10-29 22:56:39 | 显示全部楼层
USART_RX_STA是16位的数据,原子定义了最高位15是接收完成标志位,USART_RX_STA[15]=1时表示接收完成。所以0x8000好理解吧,就是最高位为1其他都为0,跟USART_RX_STA相与,低15位都被置0了只留下最高位即接收完成标志位,所以就可以通过USART_RX_STA&0x8000这样的方式来判断是否接收完成。0x3fff也是一样的。
回复

使用道具 举报

82

主题

194

帖子

0

精华

高级会员

Rank: 4

积分
596
金钱
596
注册时间
2015-10-16
在线时间
72 小时
 楼主| 发表于 2015-10-30 10:44:23 | 显示全部楼层
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
Res =USART_ReceiveData(USART1);//(USART1->DR); //读取接收到的数据

if((USART_RX_STA&0x8000)==0)//接收未完成
{
if(USART_RX_STA&0x4000)//接收到了0x0d
{
if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
else USART_RX_STA|=0x8000; //接收完成了  //为什么这里是或,可以用与吗?还有可以帮忙解释下下面几个语句的意思吗?
}
else //还没收到0X0D
{
if(Res==0x0d)USART_RX_STA|=0x4000;
else
{
USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
USART_RX_STA++;
if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收  
}
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2015-11-1 22:31:17 | 显示全部楼层
回复【4楼】liuxiangyong:
---------------------------------
请自己测试.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

5

主题

46

帖子

0

精华

高级会员

Rank: 4

积分
628
金钱
628
注册时间
2016-3-3
在线时间
68 小时
发表于 2016-11-12 11:49:41 | 显示全部楼层
USART_RX_STA与0X3FFF进行与运算是为了保证USART_RX_STA的bit15和bit14始终为了0(因为既然能执行到这一步,说明还没有接受到0X0D和0X0A,所以要让接收完成标志位和接收到0X0D标志位为0);而后面的bit0~bit13是不受影响的,即如果你原来是1,那么进行与运算后还是1,原来是0进行与运算后还是0;再结合下一句代码USART_RX_STA++;就能实现计数了。
回复

使用道具 举报

1

主题

4

帖子

0

精华

初级会员

Rank: 2

积分
54
金钱
54
注册时间
2015-7-15
在线时间
5 小时
发表于 2017-4-17 17:23:38 | 显示全部楼层
Watmin 发表于 2015-10-29 22:56
USART_RX_STA是16位的数据,原子定义了最高位15是接收完成标志位,USART_RX_STA[15]=1时表示接收完成。所以 ...

赞 真正有耐心的解答 毕竟像我这种悟性差的还是有的 好人谢谢
回复

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
19
金钱
19
注册时间
2017-9-5
在线时间
2 小时
发表于 2017-9-5 16:56:44 | 显示全部楼层
顶,好解答~~~
回复

使用道具 举报

1

主题

19

帖子

0

精华

初级会员

Rank: 2

积分
162
金钱
162
注册时间
2017-2-15
在线时间
22 小时
发表于 2018-1-11 17:28:27 | 显示全部楼层
谢谢大佬
回复

使用道具 举报

0

主题

6

帖子

0

精华

新手上路

积分
39
金钱
39
注册时间
2018-2-19
在线时间
9 小时
发表于 2018-3-6 19:18:27 | 显示全部楼层
学习了,帮顶
回复

使用道具 举报

7

主题

62

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
213
金钱
213
注册时间
2017-12-29
在线时间
37 小时
发表于 2018-3-11 21:02:19 | 显示全部楼层
Watmin 发表于 2015-10-29 22:56
USART_RX_STA是16位的数据,原子定义了最高位15是接收完成标志位,USART_RX_STA[15]=1时表示接收完成。所以 ...

刚学  感觉你解释的很好
回复

使用道具 举报

0

主题

3

帖子

0

精华

新手上路

积分
24
金钱
24
注册时间
2018-3-11
在线时间
5 小时
发表于 2018-3-12 21:13:51 | 显示全部楼层
0xtobit 发表于 2016-11-12 11:49
USART_RX_STA与0X3FFF进行与运算是为了保证USART_RX_STA的bit15和bit14始终为了0(因为既然能执行到这一步, ...

学习了,解开心头的一大烦恼
回复

使用道具 举报

56

主题

343

帖子

0

精华

高级会员

Rank: 4

积分
977
金钱
977
注册时间
2016-3-8
在线时间
267 小时
发表于 2018-3-12 21:25:23 | 显示全部楼层
少年基础不行啊。
回复

使用道具 举报

2

主题

14

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
260
金钱
260
注册时间
2017-7-17
在线时间
33 小时
发表于 2018-3-12 22:13:43 | 显示全部楼层
楼主,原子哥的编程风格还是挺有技巧的,我刚开始看的时候也有类似的疑问,但是多看两遍就能理解明白了不难的,其实还可以用位段操作来定义,更加直观,我这里用HAL库编写的,你可以参考一下。

#ifndef        __TIME3_H
#define        __TIME3_H
#include "stm32f4xx_hal.h"

struct x_entry
{
    unsigned int Count :8;                                //设置定时器溢出次数
    unsigned int Sta:1;                                //设置捕获下降沿开始状态
    unsigned int Final :1;                                //标定捕获完整低电平状态
};

void        Time3_Init(uint32_t arr, uint16_t prd);

#endif



#include "time3.h"
#include "delay.h"
#include "stm32f4xx_hal.h"


TIM_HandleTypeDef         TIME_htim;
TIM_IC_InitTypeDef        Tim3_Config;
uint32_t TIM3_Val;
struct x_entry        Lpwt;

void        Time3_Init(uint32_t arr, uint16_t prd)
{       
        __HAL_RCC_TIM3_CLK_ENABLE();

        TIME_htim.Instance = TIM3;
        TIME_htim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
        TIME_htim.Init.CounterMode = TIM_COUNTERMODE_UP;
        TIME_htim.Init.Period = arr;
        TIME_htim.Init.Prescaler = prd;
        HAL_TIM_IC_Init(&TIME_htim);

        Tim3_Config.ICFilter = 0x06;
        Tim3_Config.ICPolarity = TIM_ICPOLARITY_FALLING;                //下降沿触发
        Tim3_Config.ICPrescaler = TIM_ICPSC_DIV1;
        Tim3_Config.ICSelection = TIM_ICSELECTION_DIRECTTI;

        HAL_TIM_IC_ConfigChannel(&TIME_htim, &Tim3_Config, TIM_CHANNEL_2);

        HAL_TIM_IC_Start(&TIME_htim, TIM_CHANNEL_2);

        __HAL_TIM_ENABLE_IT(&TIME_htim, TIM_IT_CC2);
}

void         HAL_TIM_IC_MspInit(TIM_HandleTypeDef *htim)
{
        if(htim->Instance == TIM3)
        {
        __HAL_RCC_GPIOB_CLK_ENABLE();
        GPIO_InitTypeDef        Time3_GPIO_Set;

        Time3_GPIO_Set.Alternate = GPIO_AF2_TIM3;
        Time3_GPIO_Set.Mode = GPIO_MODE_AF_PP;
        Time3_GPIO_Set.Pin = GPIO_PIN_5;
        Time3_GPIO_Set.Pull = GPIO_PULLUP;
        Time3_GPIO_Set.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
        HAL_GPIO_Init(GPIOB, &Time3_GPIO_Set);

        HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);
        HAL_NVIC_SetPriority(TIM3_IRQn, 2, 0);
        HAL_NVIC_EnableIRQ(TIM3_IRQn);
        }
}

void        TIM3_IRQHandler(void)
{
        HAL_TIM_IRQHandler(&TIME_htim);
}

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
        if(htim->Instance == TIM3)
        {
                if(Lpwt.Final == 0)
                {
                        if(Lpwt.Sta != 1)
                        {
                                __HAL_TIM_SET_COUNTER(&TIME_htim, 0);                                //重新设置Time3 计数器为0

                                TIM_RESET_CAPTUREPOLARITY(&TIME_htim,TIM_CHANNEL_2);                        //重新清空定时器触发状态,一定要有
                                TIM_SET_CAPTUREPOLARITY(&TIME_htim, TIM_CHANNEL_2, TIM_ICPOLARITY_RISING);                        //重新设置定时器触发状态,为上边沿触发
                                __HAL_TIM_ENABLE_IT(&TIME_htim, TIM_IT_UPDATE);                //打开定时器更新(溢出)中断
                                Lpwt.Sta = 1;                                                                                //标记捕获到一个低电平
                        }
                        else
                        {
                                TIM3_Val = __HAL_TIM_GET_COUNTER(&TIME_htim);                //读取此时Time3 计数器的值

                                TIM_RESET_CAPTUREPOLARITY(&TIME_htim,TIM_CHANNEL_2);                        //重新清空定时器触发状态,一定要有
                                TIM_SET_CAPTUREPOLARITY(&TIME_htim, TIM_CHANNEL_2, TIM_ICPOLARITY_FALLING);                        //重新设置定时器触发状态,为下边沿触发

                                __HAL_TIM_DISABLE_IT(&TIME_htim, TIM_IT_UPDATE);        //关闭定时器更新(溢出)中断
                                Lpwt.Final = 1;                                                                                //标记捕获到一个完整的低电平
                        }
                }
        }
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
        if(htim->Instance == TIM3)
        {
                if(!Lpwt.Final)
//                if(Lpwt.Sta)
                Lpwt.Count++;                       
        }
}

回复

使用道具 举报

5

主题

44

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
259
金钱
259
注册时间
2018-3-27
在线时间
40 小时
发表于 2018-9-3 11:03:48 | 显示全部楼层
为什么我串口都没开,if(USART_RX_STA&0x8000)这句都执行了。。。。。。。。。。。。
回复

使用道具 举报

0

主题

109

帖子

0

精华

初级会员

Rank: 2

积分
167
金钱
167
注册时间
2018-9-2
在线时间
8 小时
发表于 2018-9-3 11:29:27 | 显示全部楼层
学习了,非常好的东西,支持
回复

使用道具 举报

6

主题

58

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
249
金钱
249
注册时间
2015-10-7
在线时间
50 小时
发表于 2019-1-12 09:39:33 | 显示全部楼层
为什么不分开呢,计数跟标志用两个变量不就行了。
回复

使用道具 举报

40

主题

259

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
459
金钱
459
注册时间
2016-5-19
在线时间
192 小时
发表于 2019-4-8 16:01:05 | 显示全部楼层
0xtobit 发表于 2016-11-12 11:49
USART_RX_STA与0X3FFF进行与运算是为了保证USART_RX_STA的bit15和bit14始终为了0(因为既然能执行到这一步, ...

解释的很好,恍然大悟啊
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-22 22:02

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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