嵌入式系统实用C语言代码段

获取CPU温度

应用可以定时获取CPU温度,以便在程序异常崩溃时分析潜在原因,其中CPU温度可能是一个关键因素。

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

#define CPU_TEMP_FILE0 "/sys/devices/virtual/thermal/thermal_zone0/temp"

struct cpu_temperature {
    int integer_part;
    int decimal_part;
};

typedef struct cpu_temperature cpu_temperature_t;

cpu_temperature_t get_cpu_temperature(const char *_cpu_temp_file) {
    FILE *fp = fopen(_cpu_temp_file, "r");
    cpu_temperature_t cpu_temperature = {0};
    int temp = 0;

    if (fp == NULL) {
        printf("fopen file error\n");
        return cpu_temperature;
    }

    fscanf(fp, "%d", &temp);
    cpu_temperature.integer_part = temp / 1000;
    cpu_temperature.decimal_part = (temp % 1000) / 100;

    fclose(fp);

    return cpu_temperature;
}

int main(int argc, char *argv[]) {
    cpu_temperature_t cpu_temperature = get_cpu_temperature(CPU_TEMP_FILE0);
    printf("cpu_temperature = %d.%d ℃\n", cpu_temperature.integer_part, cpu_temperature.decimal_part);
    return 0;
}

获取文件大小

有时需要获取某个文件的大小,例如在发送文件内容之前需要知道文件的确切大小。

#include <sys/stat.h>  
#include <unistd.h>  
#include <stdio.h>  

long get_file_size(const char *_file_name) {
    FILE *fp = fopen(_file_name, "r");
    if (fp == NULL) {
        printf("fopen error\n");
        return -1;
    }

    fseek(fp, 0L, SEEK_END);
    long size = ftell(fp);
    fclose(fp);

    return size;
}

int main() {
    #define FILE_NAME  "./get_file_size"
    long file_size = get_file_size(FILE_NAME);
    printf("file_size = %ld\n", file_size);

    return 0;
}

获取时间戳

系统时间戳在日志输出时非常有用,可以附带时间戳数据,方便后续分析。

#include <stdio.h>   
#include <sys/time.h>

long long get_sys_time_ms(void) {
    struct timeval sys_current_time;
    gettimeofday(&sys_current_time, NULL);
    return ((long long)sys_current_time.tv_sec * 1000) + (sys_current_time.tv_usec / 1000);
}

int main(int argc, char *argv[]) {
    long long cur_sys_time = get_sys_time_ms();
    printf("cur_sys_time = %lld ms\n", cur_sys_time);
    return 0;
}

快速获取结构体成员大小及偏移量

获取结构体成员大小及偏移量的方式有多种,最简便的方式如下:

#include <stdio.h>   

// 获取结构体成员大小
#define  GET_MEMBER_SIZE(type, member)   sizeof(((type*)0)->member)

// 获取结构体成员偏移量
#define  GET_MEMBER_OFFSET(type, member)  ((size_t)(&(((type*)0)->member)))

typedef struct _test_struct0 {
    char x;  
    char y; 
    char z;
} test_struct0;

typedef struct _test_struct1 {
    char a;  
    char c; 
    short b;         
    int d;
    test_struct0 e;
} test_struct1;

int main(int argc, char *argv[]) {
    printf("GET_MEMBER_SIZE(test_struct1, a) = %ld\n", GET_MEMBER_SIZE(test_struct1, a));
    printf("GET_MEMBER_SIZE(test_struct1, c) = %ld\n", GET_MEMBER_SIZE(test_struct1, c));
    printf("GET_MEMBER_SIZE(test_struct1, b) = %ld\n", GET_MEMBER_SIZE(test_struct1, b));
    printf("GET_MEMBER_SIZE(test_struct1, d) = %ld\n", GET_MEMBER_SIZE(test_struct1, d));
    printf("GET_MEMBER_SIZE(test_struct1, e) = %ld\n", GET_MEMBER_SIZE(test_struct1, e));
    printf("test_struct1 size = %ld\n", sizeof(test_struct1));

    printf("GET_MEMBER_OFFSET(a): %ld\n", GET_MEMBER_OFFSET(test_struct1, a));
    printf("GET_MEMBER_OFFSET(c): %ld\n", GET_MEMBER_OFFSET(test_struct1, c));
    printf("GET_MEMBER_OFFSET(b): %ld\n", GET_MEMBER_OFFSET(test_struct1, b));
    printf("GET_MEMBER_OFFSET(d): %ld\n", GET_MEMBER_OFFSET(test_struct1, d));
    printf("GET_MEMBER_OFFSET(e): %ld\n", GET_MEMBER_OFFSET(test_struct1, e));

    return 0;
}

获取MAC地址

MAC地址有时会用作设备ID,是设备的唯一标识符之一。

#include <stdio.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <string.h>

int get_netif_mac(const char *_ifr_name, uint8_t *_mac) {
    struct ifreq m_ifreq;
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    
    if (sock < 0) {
        printf("socket error\n");
        return -1;
    }

    strcpy(m_ifreq.ifr_name, _ifr_name);
    if (ioctl(sock, SIOCGIFHWADDR, &m_ifreq) < 0) {
        printf("ioctl error\n");
        close(sock);
        return -1;
    }

    snprintf((char *)_mac, 32, "%02x%02x%02x%02x%02x%02x", 
             (uint8_t)m_ifreq.ifr_hwaddr.sa_data[0],
             (uint8_t)m_ifreq.ifr_hwaddr.sa_data[1],
             (uint8_t)m_ifreq.ifr_hwaddr.sa_data[2],
             (uint8_t)m_ifreq.ifr_hwaddr.sa_data[3],
             (uint8_t)m_ifreq.ifr_hwaddr.sa_data[4],
             (uint8_t)m_ifreq.ifr_hwaddr.sa_data[5]);

    close(sock);
    return 0;
}

int main(int argc, char **argv) {
    char mac_str[32] = {0};
    get_netif_mac("wlan1", mac_str);
    printf("mac = %s\n", mac_str);

    return 0;
}

获取IP地址

有时需要获取本机IP以供显示。

#include <stdio.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>

int get_local_ip(const char *_ifr_name, char *_ip) {
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd == -1) {
        printf("socket error\n");
        return -1;
    }

    struct ifreq ifr;
    strncpy(ifr.ifr_name, _ifr_name, IFNAMSIZ);
    ifr.ifr_name[IFNAMSIZ - 1] = '\0';

    if (ioctl(sockfd, SIOCGIFADDR, &ifr) < 0) {
        printf("ioctl error\n");
        close(sockfd);
        return -1;
    }

    struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr;
    strncpy(_ip, inet_ntoa(sin->sin_addr), 32);

    close(sockfd);
    return 0;
}

int main(int argc, char **argv) {
    char ip_str[32] = {0};
    get_local_ip("wlan1", ip_str);
    printf("ip = %s\n", ip_str);

    return 0;
}

文件操作

文件操作在开发中非常常见,可以根据实际需求封装一层,方便使用。

#include <stdio.h>   

static int file_opt_write(const char *filename, void *ptr, int size) {   
    FILE *fp = fopen(filename, "wb");
    if (fp == NULL) {
        printf("open %s file error!\n", filename);
        return -1;   
    }
    
    size_t num = fwrite(ptr, 1, size, fp);
    if (num != size) {
        fclose(fp);
        printf("write %s file error!\n", filename);
        return -1;
    } 

    fclose(fp);
    return num;
}

static int file_opt_read(const char *filename, void *ptr, int size) {
    FILE *fp = fopen(filename, "rb");
    if (fp == NULL) {
        printf("open %s file error!\n", filename);
        return -1;
    }
    
    size_t num = fread(ptr, 1, size, fp);
    if (num != size) {
        fclose(fp);
        printf("read %s file error!\n", filename);
        return -1;
    } 
    fclose(fp);
    return num;
}

typedef struct _test_struct {
    char a;  
    char c; 
    short b;         
    int d;
} test_struct;

int main(int argc, char *argv[]) {
    #define FILE_NAME  "./test_file"

    test_struct write_data = {1, 3, 2, 4};
    printf("write_data.a = %d\n", write_data.a);
    printf("write_data.b = %d\n

", write_data.b);
    printf("write_data.c = %d\n", write_data.c);
    printf("write_data.d = %d\n", write_data.d);
    file_opt_write(FILE_NAME, &write_data, sizeof(test_struct));

    test_struct read_data = {0};
    file_opt_read(FILE_NAME, &read_data, sizeof(test_struct));
    printf("read_data.a = %d\n", read_data.a);
    printf("read_data.b = %d\n", read_data.b);
    printf("read_data.c = %d\n", read_data.c);
    printf("read_data.d = %d\n", read_data.d);

    return 0;
}

进度条

在执行一些耗时操作时,进度条可以方便地显示当前的进度。

#include <stdio.h>    
#include <string.h>    
#include <unistd.h>    

typedef struct _progress {
    int cur_size;
    int sum_size;
} progress_t;

void progress_bar(progress_t *progress_data) {    
    int percentage = (int)(progress_data->cur_size * 100 / progress_data->sum_size);
    char proc[102] = {0};

    printf("percentage = %d %%\n", percentage);

    if (percentage <= 100) {
        for (int cnt = 0; cnt <= percentage; cnt++) {
            printf("[%-100s] [%d%%]\r", proc, cnt);
            fflush(stdout);  
            proc[cnt] = '#';  
            usleep(100000);
        }
    }  
    printf("\n");
}

int main(int argc, char *argv[]) {
    progress_t progress_test = {65, 100};
    progress_bar(&progress_test);
    
    return 0;
}  

日志输出

日志输出常常需要带一些格式化信息,以下是一个简单的日志输出方式。

#include <stdio.h> 

#define LOG_D(fmt, args...) do { \
                                printf("<<File:%s  Line:%d  Function:%s>> ", __FILE__, __LINE__, __FUNCTION__); \
                                printf(fmt, ##args); \
                            } while(0)

int main(int argc, char *argv[]) {
    char ch = 'a';
    char str[10] = "ZhengN";
    float float_val = 10.10;
    int num = 88;
    double double_val = 10.123456;

    LOG_D("字符为 %c \n", ch);
    LOG_D("字符串为 %s \n", str);
    LOG_D("浮点数为 %f \n", float_val);
    LOG_D("整数为 %d\n", num);
    LOG_D("双精度值为 %lf \n", double_val);
    LOG_D("八进制值为 %o \n", num);
    LOG_D("十六进制值为 %x \n", num);

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sagima_sdu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值