1. Preface
It was another late night, and I no longer know how many consecutive days I had no regular rest. Early in each day, I decided to go to bed earlier in the evening, but at night I came to think and study or to do something impulsively, so I quickly finished writing and sleeping.
This is my first Linux driver based on the Full Log a40i platform. It may not be a special standard or use the device tree. It is not perfect. Everything is difficult at the beginning. I will continue to update the series of A40i usage notes after the beginning.
2. Environment
Full log A40i
linux3.10
3. Body
This article is mainly to record the code, the detailed description of the function I also did not say, a large number of online teaching videos, are more professional.
Why do we have to write the underlying drivers? The main reason is that when it comes to the project of interface development, we have already used the qt interface development, which is equivalent to turning to the Linux platform, no longer using stm32 for interface development, or 32 for no interface development or small screen oled or dot matrix screen, some control classes are still used. Now that Linux is used as the upper machine, there are some underlying ic drivers to read information. Here I use the hx711 reading weight, but I don't want to attach a 32 to use serial port to communicate. The main reason is that I don't want to take up extra board space, because Linux can drive ic itself. Why give up using 32 just because I won't drive development? So just learn, it's almost a week to be in the current position, and to watch video + actually knock code to verify, you've got the basic framework.
In the following body, the hx711 driver uses a c file and an application layer file
The driver file core code is as follows:
//Entry: insmod static int hx711_init(void) { int err; int i; printk(KERN_INFO "hx711_drv_init\n"); //Register Character Device major = register_chrdev(0, "hx711_drv", &hx711_drv); //Parameter 1:0 assigns device number dynamically, parameter 2: device name, parameter 3: file operation structure//returns the requested device number //Create a class and register it with the kernel hx711_class = class_create(THIS_MODULE, "hx711_class");//Parameter 1:owner, parameter 2:class name//Return class struct pointer err = PTR_ERR(hx711_class); if (IS_ERR(hx711_class)) { printk(KERN_ERR "hx711_class err\n"); //Uninstall registered devices unregister_chrdev(major, "hx711_drv");//Parameter 1: assigned device number, parameter 2: device name return -1; } //Create a device file informing the user that the name of the creation in the'/dev/'directory is hx711_ Device files for class-x device_create(hx711_class, NULL, MKDEV(major, 0), NULL, "hx711_class-0", 0); //Parameter 1:class structure pointer, parameter 3:device number, parameter 5:node name, parameter 6:secondary device number //Initialize io function for(i = 0; i < ARRAY_SIZE(led_info); i++) {//Traversing led_info structure int result = gpio_request(led_info[i].gpio,led_info[i].name);//Apply for GPIO hardware resources from the kernel first; if(result!=0){//Determine whether the GPIO resource requested is successful or not, and fail to return a prompt printk(KERN_ERR "GPIO%d has used...led init err!\n",led_info[i].gpio);//Print error message return -1; } } gpio_direction_output(led_info[0].gpio, 0);//Set GPIO as output function, output 0//sclk gpio_direction_input(led_info[1].gpio);//Set GPIO as input function//sda printk(KERN_INFO "hx711_drv_init ok...\n"); return 0; } //Export: rmmod static void hx711_exit(void) { int i; //Release gpio for(i = 0; i < ARRAY_SIZE(led_info); i++) {//Traversing led_info structure gpio_free(led_info[i].gpio);//Release GPIO hardware resources } //Delete Device Class device_destroy(hx711_class, MKDEV(major, 0));//Parameter 1:class structure pointer, parameter 2:device number //Unregister class class_destroy(hx711_class);//Parameter: class struct pointer //Uninstall registered devices unregister_chrdev(major, "hx711_drv");//Parameter 1: assigned device number, parameter 2: device name printk(KERN_INFO "hx711_drv_exit\n"); }
unsigned long HX711_Read(void) //Read data read by 711 { unsigned long val; unsigned char i; HX711_SCL1_L(); val = 0; while(HX711_SDA1_IN()); udelay(1); for(i=0;i<24;i++){ HX711_SCL1_H(); val=val<<1; udelay(1); HX711_SCL1_L(); if(HX711_SDA1_IN()) val++; udelay(1); } HX711_SCL1_H(); val = val^0x800000; udelay(1); HX711_SCL1_L(); udelay(1); return val; } int hx711_buffer=0;//Define hx711_buffer to accept information read by hx711read int weight_maopi=0;//Fur weight int weight_shiwu=0;//Physical weight //Obtain fur weight and record int Get_Maopi(void) { hx711_buffer=HX711_Read(); weight_maopi=hx711_buffer; return weight_maopi; } //Obtain net weight and record int Get_Weight(void) { hx711_buffer=HX711_Read(); if(hx711_buffer>weight_maopi) weight_shiwu=hx711_buffer-weight_maopi; // weight_shiwu=weight_shiwu/100; // weight_shiwu=(unsigned int)((float)weight_shiwu/4.30+0.05);// Each sensor needs to correct the divisor of 4.30. Increase this value when you find that the weight tested is too large. If the measured weight is small, reduce the change. This value is generally between 4.0 and 5.0. Depending on the linear slope of the sensor. return weight_shiwu; }
The application file code is as follows:
char *hx711_PATH = "/dev/hx711_class-0"; int main(int argc, char **argv) { int fd; int weight_int; double weight_double; /* Open File */ fd = open(hx711_PATH, O_RDWR); if (fd == -1){ printf("can not open file %s\n", hx711_PATH); return -1; } /* read file */ weight_int = 1; read(fd, &weight_int, sizeof(int));//Reading fur printf("maopi = %d\r\n",weight_int); while(1){ usleep(100000);//100 ms delay weight_int = 2; read(fd, &weight_int, sizeof(int));//Read Net Weight weight_double = weight_int; weight_double = weight_double/100; weight_double=(unsigned int)((float)weight_double/4.30+0.05);//Each sensor needs to correct the divisor of 4.30. Increase this value when you find that the weight tested is too large. If the measured weight is small, reduce the change. This value is generally between 4.0 and 5.0. Depending on the linear slope of the sensor. printf("weight = %.4fg\r\n",weight_double); } close(fd); return 0; }
The previous section describes how to compile driver files and cross-compile application files, and finally compile to generate ko files and executable program files, as shown below. Downloads from resources are
The following commands are used:
- lsmod View Loaded Kernel Modules
- insmod Load Kernel Module
- rmmod Uninstall Kernel Module
- dmesg View Log Information
- Dmesg-c Clears Log Information
- ls / dev View Device Node
- Cat/proc/devices View device number
The final test results are as follows:
IV. Conclusion
Quick Decision, Next Driver, Ready to Drive AD7606, Start~