Linux 字符設備控制

main函數

int main(int argc, char const *argv[])
{
    /* code */
    return 0;
}

argc:參數的個數(argument count)
*argv:存儲輸入字符的數組(argument value)
-------argv[0]爲程序名稱

不傳參的時候定義爲

int main(void)

函數main的返回值爲int型,用於判斷程序是否執行成功;
eg. 0爲成功 -1爲失敗

atoi函數

atoi (表示 ascii to integer)是把字符串轉換成整型數的一個函數,應用在計算機程序和辦公軟件中。int atoi(const char *nptr) 函數會掃描參數 nptr字符串,會跳過前面的空白字符(例如空格,tab縮進)等。如果 nptr不能轉換成 int 或者 nptr爲空字符串,那麼將返回 0 [1] 。特別注意,該函數要求被轉換的字符串是按十進制數理解的。

點燈應用

根據我的板子,燈的設備節點在/dev/leds目錄下;這兩個燈當對應的IO輸出高電平時亮,輸出低電平時滅;即在相應的寄存器寫入相應的值即可。

在這裏插入圖片描述
如果是直接對寄存器操作,上面跑的操作系統是不是有點浪費?

Linux中有一個專門操作IO口的函數,(需要添加頭文件 #include <unistd.h>)

int ioctl(int fd, int request, int cmd);

參數fd爲open返回的句柄 ---- 需先 open 設備節點,獲取到句柄後ioctl才能對其操作?

參數 request 和參數 cmd,由內核驅動決定具體操作,例如 request 可以代表那個 IO 口,cmd 代表對 IO 進行什麼樣的操作,也可以反過來。具體的含義由驅動工程師在驅動中 switch決定

返回值:0表示成功,-1表示出錯。

#include <stdio.h>
#include <stdlib.h>

#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define LED_NUM 2					//定義LED數量爲2
#define LED_C 2							//LED控制爲0或1 不能超過2

/*--------------------------------------------------------------------------------------
argv[1]爲對應的IO口                     IO = 0  LED2, IO = 1 LED3				     
argv[2]爲cmd							cmd = 0 LED OFF, cmd = 1 LED ON     
---------------------------------------------------------------------------------------*/
int main(int argc, char *argv[])
{
    int fd, led_num, led_c;
    char *leds = "/dev/leds";
    led_num = LED_NUM;
    led_c = LED_C;
    
    printf("argv1 is command,argv2 is IO\n");

	/*對傳入的參數進行判斷,超出範圍直接退出-*/
    if(atoi(argv[1])>=led_c)
    {
        printf("argv[1] is 0 or 1\n");
        exit(1);
    }

    if(atoi(argv[2])>=led_c)
    {
        printf("argv[2] is 0 or 1\n");
        exit(1);
    }

		
    if((fd = open(leds, O_RDWR|O_NOCTTY|O_NDELAY))<0)/*傳入的參數正確,執行打開設備節點的操作*/
    {
        printf("open %s failed\n",leds);
    }
    
    else							/*打開設備節點成功,ioctl將使用句柄將參數傳入內核*/
    {
        ioctl(fd,atoi(argv[1]),atoi(argv[2]));
        printf("ioctl %s success\n",leds);

    }

    close(fd);
    /*使用完成後關閉句柄,以防一直佔用影響到其他程序*/

    return 0;
}

讀取ADC的值

ADC的設備節點也是在/dev/adc目錄下
ADC會將採集到的值存到某個寄存器中,我們只要獲取這個寄存器的值後再根據實際進行轉換就可以了。
同樣的需要先打開設備節點獲取到句柄,然後使用read函數來獲取相應寄存器的值。

man 2 read獲取一下read函數的使用方法
在這裏插入圖片描述
需要包含#include <unistd.h> 頭文件

read(int fd, void *buf, size_t count);

fd爲句柄;
*buf 讀取到的數據
count 請求讀取的字節數

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <stdint.h>
#include <termios.h>

main()
{
    int fd;
    char *adc = "/dev/adc";
    char buffer[512];
    int len = 0, r = 0;

    memset(buffer,0,sizeof(buffer));		//申請一塊新的內存初始化buffer
    printf("adc is ready!\n");	

    if((fd = open(adc, O_RDWR|O_NOCTTY|O_NDELAY))<0)
    {
        printf("open %s failed\n",adc);
    }
    else
    {
        printf("open adc sucess!\n");
        
        len = read(fd,buffer,10);				//讀取adc的值,因爲我的板子上ADC能讀到的最大值爲0xFFF,所以count設置爲10個字節足夠了。
        if(len == 0)
            printf("return null\n");
        else
        {
            r = atoi(buffer);
            r = (int)(r*10000/4095);
            printf("\n res value is %d \n",r);   //將讀取到的ADC的值轉換成當前電阻值
        }   
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章