嵌入式系統是現代科技領域中的關鍵組成部分,貫穿于各個行業,從汽車到醫療設備
時間:2024-02-19 來源:華清遠見
作為一名嵌入式工程師,在學習和工作中肯定會遇到很多相同的程序問題,這時候我們就需要把一下自己的一些積累的代碼,copy過來直接拿來用或者簡單拿來修改修改使用,本文將介紹幾個實用的嵌入式C程序示例,并提供相應的代碼解析,幫助讀者更好地理解和應用這些示例。 代碼以實用和幫助理解一些現象為主,如有缺陷,歡迎指出。
1. 日志時間的寫入
下面程序實現:將當前的時間寫入到time.txt的文件中,如果ctrl+c退出之后,在再次執行支持斷點續寫。在一些日志文件的寫入時,可以選擇在后面填寫當前的時間。
#include <stdio.h>
#include <string.h>
#include <time.h>
#define PRINT_ERR(errmsg) \
do { \
perror(errmsg); \
printf("%s:%s:%d\n",__FILE__,__func__,__LINE__);\
return -1; \
} while (0)
int get_file_line(FILE* fp)
{
int line=0;
char s[30];
// 循環讀文件
while (fgets(s, 30, fp) != NULL) {
if (s[strlen(s) - 1] == '\n')
line++;
}
return line;
}
int main(int argc, const char* argv[])
{
time_t ts, ots;
struct tm* tm;
char tim[50] = { 0 };
FILE* fp;
int line = 0;
if ((fp = fopen("./time.txt", "a+")) == NULL)
PRINT_ERR("fopen error");
line = get_file_line(fp);
ts = ots = 0;
while (1) {
if ((ts = time(NULL)) == -1)
PRINT_ERR("time error");
if (ts != ots) {
ots = ts;
if ((tm = localtime(&ts)) == NULL)
PRINT_ERR("localtime error");
snprintf(tim, sizeof(tim), "%d.%d-%02d-%02d %02d:%02d:%02d\n",
line++, tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
fputs(tim, fp);
fflush(fp);
}
}
fclose(fp);
return 0;
}
程序現象:

2. 將十六進制字符串轉換為整型數字
下面程序實現:將16進制的字符串轉換為10進制的數字。
#include <stdio.h>
int hex_to_int(char hex[]) {
int decimal = 0;
int digit_value;
int i = 0;
// 計算每個十六進制位的值,并將其相加
while (hex[i] != '\0') {
char current_char = hex[i];
if (current_char >= '0' && current_char <= '9') {
digit_value = current_char - '0';
} else if (current_char >= 'a' && current_char <= 'f') {
digit_value = current_char - 'a' + 10;
} else if (current_char >= 'A' && current_char <= 'F') {
digit_value = current_char - 'A' + 10;
} else {
printf("Invalid hexadecimal string.\n");
return 0;
}
decimal = decimal * 16 + digit_value;
i++;
}
return decimal;
}
int main() {
char hex_string[] = "ABCD"; // 十六進制字符串
int decimal = hex_to_int(hex_string); // 將十六進制字符串轉換為整型數字
printf("Decimal: %d\n", decimal); // 打印轉換后的十進制數
return 0;
}
代碼運行現象:
3.給BMP格式的圖片打馬賽克
下面程序實現對BMP格式的圖片打馬賽克:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
unsigned char b;
unsigned char g;
unsigned char r;
} RGB_t;
#define MOSIC_WIDTH 10
#define MOSIC_HIGH 10
#define PRINT_ERR(errmsg) \
do { \
perror(errmsg); \
printf("%s:%s:%d\n",__FILE__,__func__,__LINE__);\
return -1; \
} while (0)
int main(int argc, const char* argv[])
{
FILE* fp;
unsigned int size, offset, width, high;
unsigned short pix;
// 1.對命令行參數校驗
if (argc != 2) {
fprintf(stderr, "input error,try again\n");
fprintf(stderr, "usage: ./a.out xxx.bmp\n");
return -1;
}
// 2.打開圖片
if ((fp = fopen(argv[1], "r+")) == NULL)
PRINT_ERR("fopen error");
// 3.讀取圖片信息
fseek(fp, 2, SEEK_SET);
fread(&size, 4, 1, fp);
printf("size = %d\n", size);
fseek(fp, 4, SEEK_CUR);
fread(&offset, 4, 1, fp);
printf("offset = %d\n", offset);
fseek(fp, 18, SEEK_SET);
fread(&width, 4, 1, fp);
printf("width = %d\n", width);
fread(&high, 4, 1, fp);
printf("high = %d\n", high);
fseek(fp, 2, SEEK_CUR);
fread(&pix, 2, 1, fp);
printf("pix = %d\n", pix);
// 4.打馬賽克
RGB_t(*img)[width] = malloc(width * high * (pix / 8));
// 4.1將圖片的數據讀出來
fseek(fp, 54, SEEK_SET);
for (int i = 0; i < high; i++) {
for (int j = 0; j < width; j++) {
fread(&img[i][j], sizeof(RGB_t), 1, fp);
}
}
// 4.2打馬賽克
for (int i = 0; i < (high / MOSIC_HIGH) * MOSIC_HIGH; i += MOSIC_HIGH) {
for (int j = 0; j < (width / MOSIC_WIDTH) * MOSIC_WIDTH; j += MOSIC_WIDTH) {
for (int x = 0; x < MOSIC_HIGH; x++) {
for (int y = 0; y < MOSIC_WIDTH; y++) {
img[i + x][j + y] = img[i][j];
}
}
}
}
// 4.3將圖片的數據寫入到文件中
fseek(fp, 54, SEEK_SET);
for (int i = 0; i < high; i++) {
for (int j = 0; j < width; j++) {
fwrite(&img[i][j], sizeof(RGB_t), 1, fp);
}
}
return 0;
}
程序現象:
4.對BMP程序打馬賽克進階
下面程序利用C++ QT程序將上面的功能進行了拓展,可以實現界面選擇圖片處理,當你理解了上面的程序之后,利用C++結合QT就能快速上手做出一個圖像處理的demo程序。
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPushButton>
#include <QImage>
#include <QLabel>
#include <QFileDialog>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void openImage();
void processImage();
void saveImage();
private:
QLabel *imageLabel; // 用于顯示圖像的控件
QImage originalImage; // 原始圖像
QImage processedImage; // 處理后的圖像
};
#endif // MAINWINDOW_H
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.cpp
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
this->setFixedSize(1250,800);
imageLabel = new QLabel(this);
setCentralWidget(imageLabel);
QPushButton *openButton = new QPushButton("打開圖片", this);
connect(openButton, &QAbstractButton::clicked, this, &MainWindow::openImage);
QPushButton *processButton = new QPushButton("處理圖片", this);
connect(processButton, &QAbstractButton::clicked, this, &MainWindow::processImage);
processButton->move(150,0);
QPushButton *saveButton = new QPushButton("保存圖片", this);
connect(saveButton, &QAbstractButton::clicked, this, &MainWindow::saveImage);
saveButton->move(300,0);
}
MainWindow::~MainWindow()
{
}
void MainWindow::openImage()
{
QString imagePath = QFileDialog::getOpenFileName(this, "選擇圖像", "", "BMP 圖像 (*.bmp)");
if (!imagePath.isEmpty())
{
originalImage.load(imagePath);
imageLabel->setPixmap(QPixmap::fromImage(originalImage));
imageLabel->adjustSize();
}
}
void MainWindow::processImage()
{
if (!originalImage.isNull())
{
processedImage = originalImage.copy(); // 復制原始圖像進行處理
int gridSize = 16; // 馬賽克塊的大小
for (int x = 0; x < processedImage.width(); x += gridSize)
{
for (int y = 0; y < processedImage.height(); y += gridSize)
{
QRgb averageColor = processedImage.pixel(x, y);
for (int i = 0; i < gridSize; i++)
{
for (int j = 0; j < gridSize; j++)
{
int newX = qMin(x + i, processedImage.width() - 1);
int newY = qMin(y + j, processedImage.height() - 1);
processedImage.setPixel(newX, newY, averageColor);
}
}
}
}
imageLabel->setPixmap(QPixmap::fromImage(processedImage));
imageLabel->adjustSize();
}
}
void MainWindow::saveImage()
{
if (!processedImage.isNull())
{
QString savePath = QFileDialog::getSaveFileName(this, "保存圖像", "", "BMP 圖像 (*.bmp)");
if (!savePath.isEmpty())
{
processedImage.save(savePath);
}
}
}
程序現象:
5.在linux中獲取本地IP的程序
下面程序是在linux中獲取本地IP的程序:
#include <stdio.h>
#include <ifaddrs.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
#define MAX_IP_COUNT 3
#define IP_ADDR_LEN INET_ADDRSTRLEN
int get_local_ip(char ipList[MAX_IP_COUNT][IP_ADDR_LEN]) {
struct ifaddrs *ifAddrStruct;
char ipAddr[IP_ADDR_LEN];
void *tmpAddrPtr;
int ipCount = 0;
// 獲取網絡接口列表
if (getifaddrs(&ifAddrStruct) == -1) {
perror("getifaddrs");
return 0;
}
// 遍歷網絡接口列表
while (ifAddrStruct != NULL) {
if (ifAddrStruct->ifa_addr->sa_family == AF_INET) {
tmpAddrPtr = &((struct sockaddr_in *)ifAddrStruct->ifa_addr)->sin_addr;
inet_ntop(AF_INET, tmpAddrPtr, ipAddr, IP_ADDR_LEN);
// 排除回環地址
if (strcmp(ipAddr, "127.0.0.1") != 0) {
if (ipCount < MAX_IP_COUNT) {
memcpy(ipList[ipCount], ipAddr, IP_ADDR_LEN);
ipCount++;
} else {
break;
}
}
}
ifAddrStruct = ifAddrStruct->ifa_next;
}
freeifaddrs(ifAddrStruct);
return ipCount;
}
int main() {
char ipAddrList[MAX_IP_COUNT][IP_ADDR_LEN];
int addrCount;
memset(ipAddrList, 0, sizeof(ipAddrList));
addrCount = get_local_ip(ipAddrList);
if (addrCount > 0) {
printf("Server Local IP:\n");
for (int i = 0; i < addrCount; i++) {
printf("%d: %s\n", i+1, ipAddrList[i]);
}
} else {
printf("No local IP address found.\n");
}
return 0;
}
程序現象:

