雨滴科技技术论坛

 找回密码
 立即注册
查看: 4143|回复: 4

msOS学习之路(4)

[复制链接]

68

主题

274

帖子

2647

积分

金牌会员

Rank: 6Rank: 6

积分
2647
扫一扫,手机访问本帖
发表于 2018-7-25 20:10:08 | 显示全部楼层 |阅读模式
本帖最后由 DataH 于 2018-8-5 23:14 编辑

msOS设备层简单理解
1 设备层相关定义
设备层的相关定义是在device.h文件中定义的,包括按键、模拟量输入、数字量输入/输出枚举或者类型定义等,对于一些结构体的理解,例如:ADC结构体,定义了ADC的使用到的一些成员变量。
  1. typedef struct
  2. {
  3.          ushort A0;
  4.          ushort A1;
  5.          ushort A2;
  6.          ushort A3;
  7.          ushort * pA0;   # 获取数据所在寄存器地址
  8.          ushort * pA1;
  9.         ushort * pA2;
  10.          ushort * pA3;
  11. }AdcStruct;
复制代码
2 ADC
ADC的初始化分为两个部分一个是IO初始化,另一个是ADC本身初始化。接着进行DMA设置,进行高速采样。在stm32提高了两到三个ADC端口,对于stm32可以使用DMA做对一个ADC1做高速采样,而ADC2不能使用DMA做高速采样,可以使用节拍或者定时器做低速的采样,这样可以把速度不同的分开,以防止高速的拖累低速的设备,这样两个高低速配合,以调高效率。
DMA把采用过来的数据放到DmaBuffer里面,总共有5路,4路ADC采样和1路温度,深度为8个表示每一路放8个数据。在采用高速的节拍对数据进行处理,在AdcSystick10000Routine函数中是对采用数据进行数据处理,进行了一些滤波操作,这里的滤波是对八个数据做累加求平均值,而对于温度部分在获取到模拟量以后需要进行线性转,映射成温度值。经过节拍滤波后放进寄存器里面。然后把存放在ADC数组中的数据与数据库进行连接,实现的代码为:

  1. static void PortRegister(void)
  2. {
  3.     AppDataPointer->Adc.pA0 = &Adc[0];
  4.     AppDataPointer->Adc.pA1 = &Adc[1];
  5.     AppDataPointer->Adc.pA2 = &Adc[2];
  6.     AppDataPointer->Adc.pA3 = &Adc[3];
  7. }
复制代码

通过以上可以获取到滤波之后的ADC值,如果想要更快的获取ADC值,就直接从DmaBuffer中获取,但是这些值是没有经过滤波的,对于深度为1的场景,可以去掉系统节拍滤波这个功能。
3 DI
PLC开关输入接口,有两种模式一种是开关量输入和PWM捕获。
代码理解:pX直接与位与对接起来,因为位与直接对应的是开关量输入的信号,直接映射到位与寄存器里面。

  1. AppDataPointer->DI.pX0 = (bool *)&PaIn->Bit4;
  2. AppDataPointer->DI.pX1 = (bool *)&PaIn->Bit5;
  3. AppDataPointer->DI.pX2 = (bool *)&PaIn->Bit6;
  4. AppDataPointer->DI.pX3 = (bool *)&PaIn->Bit7;
复制代码

但是,这样的做法不是很好,因为直接获取到的数据会有噪音,所以有时候需要进行滤波,对于这个问题要解决的方式是使用节拍对获取到的值进行滤波,然后再存到一个变量中,这时候保存到这个变量的值就是经过滤波之后的值。
4 DO
DO有开关量输出和PWM输出两种状态。首先,每个信号与位与绑定,实现的代码如下:

  1. AppDataPointer->DO.pY0 = (bool *)&PbOut->Bit0;   
  2. AppDataPointer->DO.pY1 = (bool *)&PbOut->Bit1;
  3. AppDataPointer->DO.pY2 = (bool *)&PbOut->Bit12;
  4. AppDataPointer->DO.pY3 = (bool *)&PbOut->Bit13;
  5. AppDataPointer->DO.pY4 = (bool *)&PbOut->Bit14;
  6. AppDataPointer->DO.pY5 = (bool *)&PbOut->Bit15;
复制代码

对于PWM输出模式,可以通过Open(PwmEnum channel)可以选择输出的通道,设置定时器。通过SetDutyRatio函数可以设置输出的占空比。SetParameter可以设置输出的频率和占空比,对于DO部分主要就是这些函数。
5 Key 按键
按键有长按与短按的区别,按键是通过节拍来运行的,当检测到按键之后通过PostMessage()函数发出消息,让节拍处理。
6 LCD 屏
主要是用于显示用的,主要的函数有LcdDisplayString函数,实现的代码如下:
  1. // y表示显示的行号,取值为0、1、2、3。string表示要显示的内容,最多16个字节
  2. static void LcdDisplayString(byte y, string string)
  3. {
  4.     byte i;     
  5.     SendInstruct(Array[y]);
  6.     for (i = 0; i < 16; i++)
  7.         SendData(*string++);
  8. }
复制代码

还有就是要进行初始化,初始化完成之后把函数关联起来。在进行初始化的时候,一般先进行端口的初始化,然后再进行GPIO口的初始化,这样会有避免端口跳动的危险。所以,在msOS中要先对开关量信号进行初始化,然后再进行端口的配置。例如:
  1. PinClk = 0; PinCs = 0; PinData = 0; PinReset = 0; # 开关量信号
  2. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
  3. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  4. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
复制代码
7 Misc
主要是用于蜂鸣器响声,但是在按键当中的蜂鸣器没有使用到这个函数,按键的蜂鸣器使用时独立的。当要使用蜂鸣器的时候直接调用SetBeep,并设置启动方式即可。
8 Rtc 时间显示
Rtc是用于时间显示的,在节拍中被调用,模拟时间。
9 Storage 参数存储
9.1 简介
stm32中的flash中的数字只有0和1,对于里面的数值只能把1改为0而不能把0直接改为1,要把0变为1的时候要整页的擦除,才能进行更改。所以,要写数据的时候,常规的做法是先把要写的数据存储起来,然后把整页擦除掉,然后再写进去。而在msOS中使用的是另一种方法,是追加式的,追加式意思是哪个参数改了,就把哪个参数写进去就行了。但追加方式会出现重名的情况,因为每次修改之后都会进行追加,然后保存这样就出现了重名的情况,对于这种情况,在msOS中只存储最后一次值,如果还有多余的的数据,那么久把要把正业擦除掉,然后再进行保存。在使用追加式进行参数存储还需要注意的是,对于每个数据都要有保存该数据的地址,不然会造成无法使用数据的情况。所以创建一个结构体,结构体的代码如下:
  1. typedef struct
  2. {
  3.     uint Address;               //参数存储单元地址
  4.     uint Data;                  //参数存储单元数据
  5. }CellStruct;
复制代码
9.2 写入
追加式写入的函数为WriteParameter(void * dataPointer) 当传递过来一个要加入的地址以后,首先判断该地址是否为空或者已经填满,当都不是这两种情况的时候,对数据进行追加,把数据写到指定的位置上。
9.3 开机整理
对于使用追加式方式,在开机的时候需要对数据进行整理,不然会出现有错的情况,使用对数据整理的函数使用ReadAllParameter(void)函数,会清除一些垃圾数据。在数据整理的函数中,当开机的时候首先判断存储器的地址是否为空(0xffffffff),如果不为空,就把这个数据保存起来,并把数据写到对应的变量上,因为msOS有对应的数据库。对于保存了地址之后,就要判断地址是否有重叠,即判断地址是否有相等的,如果有相等的就把前面的地址设置为空,并把清理的标志(CleanFlag)设置为true。接下来就要判断CleanFlag是否为false,如果为false那么这个数据是有效的不需要进行处理。对无效数据数据处理的过程为,首先把整页进行擦除,之后再把之前保存的有效数据写回去。
10 系统节拍
系统节拍采用的是1s一万次中断,因为在msOS中上层能调用底层,底层不能调用上层,但是上层有时候需要调用系统节拍,所以在msOS中采用了注册机制,在系统节拍文件中定义了很多注册变量,在变量中存储函数指针,例如:

  1. static function Systick10000RegisterPointerBlock[Systick10000Sum] =
  2. {
  3.     Dummy, Dummy  // 这两个变量用作存储函数指针
  4. };
复制代码

从整体上来讲,系统的节拍每秒是一万次的节拍。但是,每个节拍中我们不可能放很多个函数,因为有些函数是需要低速进行的,但有些函数需要高速的进行处理,这样在msOS中采用分频的方式把他们放在不同的节拍进行处理。因为stm32的频率是72M,系统节拍是每秒10000次,所以在每个节拍中能够执行7200个指令,所以,如果很多个函数都放在同一个节拍中,指令超过7200的话会出现问题。在msOS中使用了分频的方式,保证了每个节拍执行的指令数少于7200个,并把低速和高速处理的函数分开,提高处理效率。在该开始开系统节拍的时候并没有想到这一部分这样处理的作用,但是知道以后,发现这个思想真的太完美了。
对于系统节拍的入口是SysTick_Handler函数,每秒中一万次进入这个函数。经过分频可分为每秒10000、1000和100次,把需要高速处理的函数放在每秒10000次的节拍里面,比如ADC,而对于低速处理的比如按键可以放在每秒1000次的节拍中。当上次需要用节拍的时候进行注册就可以。统计可以直接使用RegisterSystick函数进行注册,而上层的直接调用Register进行注册。
11 Timer 定时器
当使用定时器的时候就调用static void Start(int id, TimerModeEnum mode, int times, function functionPointer)函数调用开启定时器。参数mode表示选择处理的方式,有系统节拍处理和逻辑任务处理两种方式,一般在系统节拍中处理的函数是时时任务比较高的、代码量较小任务。在msOS中,对于紧急的任务可以直接用中断,优先级最高,次优先级用系统节拍,再接着就是业务逻辑,最后是菜单界面。该定时器是基于系统节拍实现的,虚拟出来的软件定时器,所以,要把执行的程序TimerSystick1000Routine放到系统节拍中,每1s会调用1000次,当开启定时器后,当定时时间到达时,就会判断是哪种模式,当是逻辑任务处理时候,就会抛出消息,在逻辑业务中进行处理,如果是系统节拍的方式,就会直接执行。
12 串口
在串口中,发送数据是用一个队列来进行发送的,将要发送的数据放到队列当中。真正的发送时在系统节拍中发送的。在系统节拍发送之前首先判断队列是否为空并行判断串口是否空闲,当达到条件时就会发送数据,在msOS中实现的代码如下:

  1. void Usart1Systick1000Routine(void)
  2. {
  3.     if (TxdQueue.Entries == 0) return;  //判断队列是否为空
  4.     if ((USART1->SR&0x80)==0) return;   // 判断串口是否忙

  5.     USART1->DR = *TxdQueue.Out++;   // 发送数据
  6.    
  7.     if (TxdQueue.Out > TxdQueue.End)
  8.         TxdQueue.Out = TxdQueue.Start;

  9.     EnterCritical();
  10.     TxdQueue.Entries--;
  11.     ExitCritical();
  12. }
复制代码

13 总结
通过学习msOS设备层,感觉还有很多不明白的地方。对设备的配置、执行过程和一些函数的作用等都不是很清楚。以上是个人的一些简单理解,有写地方可能不对,还有很多需要改进的地方,但本人目前知识有限,现阶段只能理解到这个层次,今后在更深的理解上会进行修改。

回复

使用道具 举报

280

主题

1749

帖子

7371

积分

版主

Rank: 7Rank: 7Rank: 7

积分
7371
发表于 2018-7-27 11:59:53 | 显示全部楼层
实践中掌握!
回复 支持 1 反对 0

使用道具 举报

409

主题

1838

帖子

8037

积分

版主

Rank: 7Rank: 7Rank: 7

积分
8037
QQ
发表于 2018-7-27 17:28:36 | 显示全部楼层
实践学得更快
深圳市雨滴智能智能有限公司
专业条码 RFID 手持机厂家 QQ:1464353114
微信号:15986765262
回复 支持 反对

使用道具 举报

315

主题

1780

帖子

8544

积分

论坛元老

Rank: 8Rank: 8

积分
8544
发表于 2018-7-27 18:23:36 | 显示全部楼层
系统虽小,五脏俱全啊,深入学习,你会有大发现
《《 雨滴科技 》》
雨润万物,滴水成河
回复 支持 反对

使用道具 举报

0

主题

7

帖子

34

积分

新手上路

Rank: 1

积分
34
发表于 2022-9-17 07:56:14 | 显示全部楼层
回复

使用道具 举报

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

本版积分规则

在线客服
在线咨询
咨询热线
0755-26787502-8006/8016
扫一扫二维码
直接访问本站

QQ|Archiver|手机版|小黑屋|雨滴科技  

GMT+8, 2023-3-29 05:17 , Processed in 0.088263 second(s), 11 queries , Gzip On, Memcache On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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