linux 小项目开发-1-概括和start(linux-SPI驱动小结)

it2022-06-26  90

 

项目的要求:环境温度的检测和报警系统系统介绍: 实时读取环境温度、读/写IIC接口的EEPROM、控制管显示、按键编程、串口/网口输出数据、LED显示闪烁报警、蜂鸣器响声告警,本地GUI显示状态(显示系统时间,本地天气和系统状态等)--因此构成一套简单的环境温度检测和报警系统;应用分配: (1) 使用 EEPROM 保存用户设置的最低安全温度和最高安全温度; (2) 在数码管切换显示最低安全温度、最高安全温度以及当前温度; (3) 通过按键设置最安全低温度和最高安全温度,并保存在 EEPROM; (4) 当环境温度不在安全温度范围之内时,发出声/光警报(声音-蜂鸣器,光-led快闪); (5)用串口通讯或网口tcp/ip通讯向外部传输当前的系统数据 (6)QT-GUI显示本机的状态系统拓扑图:

-----------------------------------测试驱动----------------------------------------------------

1.数码管显示-SPI驱动

(1)stm32的spi驱动初始化,主要配置两个要点:1-是总线时钟+总线的配置,2-是GPIO时钟+GPIO的管教配置,如下图 (2)linux的驱动初始化也是如此两个要点,1-确认硬件连接--要可开启设备(SPI 总线设备文件和 GPIO 属性文件),2-配置号spi总线的通讯配置(即设置 SPI 总线参数:总线极性、总线的最大频率、数据字的大小) 伪代码如下:

int main(int argc, char *argv[]) { int ret = 0; int fd_spi = 0; int fd_gpio = 0; int led_value = 0; int led_num = 0; fd_spi = open(SPI_DEVICE, O_RDWR); fd_gpio = open(GPIO_DEVICE, O_RDWR); ret = ioctl(fd_spi, SPI_IOC_WR_MODE, &mode); /* set spi mode */ ret = ioctl(fd_spi, SPI_IOC_WR_BITS_PER_WORD, &bits); /* set spi bits per word */ ret = ioctl(fd_spi, SPI_IOC_WR_MAX_SPEED_HZ, &speed); /* max speed hz */ show_led_num(fd_spi, fd_gpio, led_value, led_num); close(fd_spi); return ret; }

                  总线极性:关于SPI的总线参数--极性和时序说明总线的最大频率:SPI 总线的最大速率设置后,在使用过程并不是只能使用该频率收/发数据,而仅仅约束收/发数据时的最大频率 数据字的大小:设置 SPI 总线上每字的数据位长度

2.eeprom的掉电存储应用-iic驱动开发

stm32的初始化操作也是类似,主要两个要点:1-是总线时钟+总线的配置(地址、时钟等),2-是GPIO时钟+GPIO的管脚配置 linux的初始化也是如此(更简单),1是打开对应的硬件地址,2是配置设备(从机地址和设置地址长度); 伪代码对比如下(左为stm32的iic初始化配置,右为linux-iic驱动测试伪代码):

时序:(单字节读/写 和多字节读/写,单字节每次都有写地址,多字节--连续读/写多个字节--不需多次写地址)

3.ADC-温度检测

ADC的驱动有两种,一种是 LRADC 对应的驱动(一种 Low-ResolutionADC-LRADC 低分辨率--比如温度/电压采集!)。另一种为 HSADC对应的驱动(High-SpeedADC-HSADC高速ADC,每秒可达 2MSPS--高速 ADC,可用于摄像头数据采集);  

#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <math.h> #include <sys/ioctl.h> #include "lradc.h" #define LRADC_DEV "/dev/magic-adc" /* adc 设备文件名 */ #define CMD_VOLTAGE IMX28_ADC_CH0 /* 通道 0 读取命令 */ #define CMD_TEMPTURE IMX28_ADC_CH1 /* 通道 1 通读读取命令 */ #define R33 2000 #define V_ADC 3.3 #define T1 (273.15 + 25) #define R1 27600 #define B 3435*1000 int main(int argc,char **argv) { short buff[100]; int i, fd, value_R, value_T, cmd, ret, len = 2; float voltage, RT, temp,resistance; fd = open (LRADC_DEV,O_RDONLY); /* 打开ADC设备 */ if (fd < 0) { perror("open"); close(fd); return 0; } ret = ioctl(fd, CMD_VOLTAGE, &value_R); /* 读取通道 0 */ if(ret != 0){ perror("ioctl"); return -1; } ret = ioctl(fd, CMD_TEMPTURE, &value_T); /* 读取通道 1 */ close(fd); if(ret != 0) { perror("ioctl"); return -1; } resistance = (value_R*1.85)/4096.0; /* 计算通道 0 测量电压 */ voltage = (value_T*1.85)/4096.0; /* 计算通道 1 测量电压 */ RT = (V_ADC/voltage - 1)*R33; /* 计算热敏电阻的阻值 */ temp = 3435/log(10*RT) - 273.15; /* 计算热敏电阻的温度 */ printf("A10 电阻电压 %fV ;A11 加热电阻温度 %f\n",resistance, temp); return 0; }

 

4.键盘检测

key.ko驱动模块加载完成( rmmod key.ko)后,将在/dev/input 目录生成设备文件/dev/input/event1(无usb鼠标和usb键盘) 键盘事件的结构体:

struct input_event { struct timeval time;//有A和B两个long成员-可表示A.B秒(如a=1,B=123,表示时间启动1.123000s) __u16 type;//事件类型,0-事件提交,1-按键事件,2-相对坐标事件(鼠标),3-绝对坐标事件(触摸屏) __u16 code;//码值-与硬件相关,比如某键盘上的字母A-码值为30,B-48.. __s32 value;//value成员对于不同的输入事件有不同的意义。eg.按键事件,value可取值为:1(表示键按下)和 0(表示键提起) }

测试代码如下:

#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <linux/input.h>//加载key*.ko驱动后,会有event0/1/2..时间在input下 int main (int argc, char * argv[]) { int fd,count; struct input_event input_event_value;//input_event为input下的结构体 char input_type[20]; if (argc !=2 ) {//判断程序是否有输入参数,如果没有程序退出 printf("usage : input_type /dev/input/eventX\n"); return 0; } fd = open (argv[1], O_RDWR); if (fd < 0) {//打开输入设备,设备的名称为程序的输入参数提供 printf ("open %s failed\n", argv[1]); exit(0); } while(1) {//循环读取输入事件,然后打印事件信息的结构体 count=read(fd, &input_event_value, sizeof(struct input_event)); if (count < 0) { printf("read iput device event error \n"); return -1; } switch(input_event_value.type) {//判断事件的类型 case EV_SYN: strcpy(input_type, "SYNC"); break; case EV_REL: strcpy(input_type, "REL"); break; case EV_ABS: strcpy(input_type, "ABS"); break; case EV_KEY: strcpy(input_type, "KEY"); break; default: printf("even type unkown \n"); return -1; } printf("time:%ld.%ld",input_event_value.time.tv_sec,input_event_value.time.tv_usec); printf(" type:%s code:%d value:%d\n",input_type,input_event_value.code,input_event_value.value); } return 0; }

 

5.GPIO操作-LED/蜂鸣器开发

 

6.tcp/ip网络通讯

 

7.串口驱动

 


最新回复(0)