物联网实战--入门篇之(八)嵌入式-空气净化器(2)

/*		
================================================================================
描述 : 风扇电机初始化
输入 : 
输出 : 
================================================================================
*/
void app_motor_init(void)
{
// 使能TIM1时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
 
    // 使能GPIOA时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
 
    // 设置GPIOA_8为复用功能推挽输出
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
 
    // 初始化TIM1 PWM模式
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure;
    TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_Period = PWMPeriodValue-1; // 周期为10k
    TIM_TimeBaseStructure.TIM_Prescaler = 720 - 1; // 预分频器设置为7199,确保计数器的频率为1MHz
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

    TIM_OCStructInit(&TIM_OCInitStructure);
    TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;	
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//选择PWM模式1
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//输出比较极性选择
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//输出使能
    TIM_OC1Init(TIM1, &TIM_OCInitStructure);//初始化 TIM1 OC1
    TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);//使能CCR1自动重装
    TIM_ARRPreloadConfig(TIM1,ENABLE);//开启预装载  
    TIM_CtrlPWMOutputs(TIM1, ENABLE);//手动开启,防止与串口1冲突后不启动


    // 使能TIM1的输出比较预装载寄存器
    TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
 
    // 使能TIM1
    TIM_Cmd(TIM1, ENABLE);  
    
    
    printf("app_motor_init ok!\n");
}

在使用上就很简单了,就是不断改变PWM值就行了,如下所示。这里还有个系数0.6主要是为了防止电流过大,影响主控设备稳定。

/*		
================================================================================
描述 : 设置速度
输入 : speed 0~255,速度分为256级
输出 : 
================================================================================
*/
void app_motor_set_speed(u8 speed)
{
  g_sAirWork.fan_speed=speed;
  u16 value=speed*PWMPeriodValue/255*0.6;//系数主要是防止电机电流过大影响设备稳定
  printf("pwm val=%d\n", value);
  TIM_SetCompare1(TIM1, value);
}

二、通讯协议

这里的通讯协议是指在MQTT之上的应用层通讯协议,属于我们自定义的内容,由此我们也可以知道,协议也是一层一层堆起来的,每个场景有各自适合的协议。通讯协议在物联网系统里是最重要的,如果交流语言都不通了,还谈什么联网。

自定义协议满足自己的要求即可,但是我们的要求也不能太低,至少要满足以下几个要求:

1、二进制传输,比较高效、省流量,这在使用4G流量卡的时候就很关键了;

2、易检索,可以在一堆数据包里找到明显特征并解析,可以解决粘包问题;

3、正确性,要有校验码,确保数据正确;

4、方便代码书写,这样可以在各类系统中使用;

5、没有网络大小端问题,这是早期很多人用结构体传输时候经常碰到的问题。

上图是基本的协议框架,包含了帧头、数据长度、设备码、命令和校验码等关键通用的信息,需要注意的是,这里整形数据都采用高字节先传输的原则,比如数据总长Len,先传输Len的高8位,再传输低8位,具体的整合代码如下:

这里面有个入口参数cmd_type,根据这个项目的定义如下。

在实际使用的时候举例如下,把自己应用层的数据按你自己的顺序要求打包好发送就行了。

细心的同学会发现,上图中在传输温度数据时候比较特别,先把数值乘以10再加1000,为什么要这么操作?主要是为了保证传输的数据都是正整数,避免了网络大小端的问题,这里的乘以10是保留小数点后一位,传感器返回的数据最小是-45.0,乘以10就是-450,再加上1000就可以保证这个数值是正整数,最后再把这个正整数高8位、低8位依次存进数组内。对于接收端,解析就是一个逆向过程了,具体如下图所示,获取到原始数据后先减1000再除以10.0,这里要记得是10.0而不是10,这样才能保持小数。

对于接收端,就是按照协议一步步解析即可,代码很简洁、模式很固定的,具体的可以工程项目打开来看看。


/*		
================================================================================
描述 : 设备解析服务器下发的数据
输入 : 
输出 : 
================================================================================
*/
void app_air_recv_parse(u8 *buff, u16 len)
{
  u8 head[2]={0xAA, 0x55};
  u8 *pData=memstr(buff, len, head, 2);
  if(pData!=NULL)
  {
    u16 total_len=pData[2]<<8 | pData[3];
    u16 crcValue=pData[total_len]<<8 | pData[total_len+1];
    if(crcValue==drv_crc16(pData, total_len))
    {
      pData+=4;
      u32 device_sn=pData[0]<<24|pData[1]<<16|pData[2]<<8|pData[3];
      pData+=4;
      if(device_sn!=g_sAirWork.device_sn)//识别码确认
        return;
      u8 cmd_type=pData[0];
      pData++;
      switch(cmd_type)
      {
        case AIR_CMD_HEART://心跳包
        {
          
          break;
        }
        case AIR_CMD_DATA://数据包
        {
          
          break;
        }
        case AIR_CMD_SET_SPEED://设置风速
        {
          u8 speed=pData[0];
          pData+=1;
          app_motor_set_speed(speed);
          break;
## 最后

**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**

**深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。**

**因此收集整理了一份《2024年嵌入式&物联网开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**

![img](https://img-blog.csdnimg.cn/img_convert/b7c09345d1d17b940b737e194417ba44.png)

![img](https://img-blog.csdnimg.cn/img_convert/ad046b4df5ec09d8592f8135019123cb.jpeg)

![img](https://img-blog.csdnimg.cn/img_convert/0c4962d055b9f8bdc5b110d969b4d22b.png)

 ![img](https://img-blog.csdnimg.cn/img_convert/9e7656c038d72ca732349271fd7af7dd.png)

![img](https://img-blog.csdnimg.cn/img_convert/6b92a3c9bcce43f00aade2f539a90a03.png)

![img](https://img-blog.csdnimg.cn/img_convert/a644791de2bad947d15fe5983c20752e.png)

![](https://img-blog.csdnimg.cn/img_convert/b4237cd2f9808f250dbee7e95ba294d5.png)

 

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!**

[**如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618654289)

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**!!


学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!**

[**如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618654289)

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**!!


  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值