硬件编程是嵌入式系统开发的核心部分,它涉及到与硬件设备直接交互,通过编写程序控制硬件的行为。对于初学者来说,掌握一些常用的库函数可以大大提高编程效率和项目成功率。以下是几个在硬件编程中常用的库函数及其应用。
1. 串口通信库函数
1.1. 串口初始化
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
int serial_init(const char *dev, int baudrate) {
int fd = open(dev, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1) {
perror("open serial port failed");
return -1;
}
struct termios options;
tcgetattr(fd, &options);
cfsetispeed(&options, baudrate);
cfsetospeed(&options, baudrate);
options.c_cflag &= ~PARENB; // 清除奇偶校验位
options.c_cflag &= ~CSTOPB; // 1 停止位
options.c_cflag &= ~CSIZE; // 清除所有字符大小掩码
options.c_cflag |= CS8; // 8 数据位
options.c_cflag |= CREAD | CLOCAL; // 启用接收,忽略Modem控制线
tcsetattr(fd, TCSANOW, &options);
return fd;
}
1.2. 发送数据
#include <unistd.h>
void serial_send(int fd, const char *data, int size) {
int n = write(fd, data, size);
if (n < 0) {
perror("serial write failed");
}
}
1.3. 接收数据
#include <unistd.h>
#include <string.h>
int serial_receive(int fd, char *data, int size) {
int n = read(fd, data, size);
if (n < 0) {
perror("serial read failed");
}
return n;
}
2. I2C通信库函数
2.1. I2C初始化
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
int i2c_init(const char *dev, int speed) {
int fd = open(dev, O_RDWR);
if (fd < 0) {
perror("i2c open failed");
return -1;
}
if (ioctl(fd, I2C_SLAVE, 0x10) < 0) {
perror("i2c set slave address failed");
close(fd);
return -1;
}
return fd;
}
2.2. 发送数据
#include <unistd.h>
int i2c_send(int fd, uint8_t slave_address, const uint8_t *data, int size) {
uint8_t cmd[2];
cmd[0] = slave_address;
cmd[1] = I2C_WRITE;
if (write(fd, cmd, 2) != 2) {
perror("i2c send start failed");
return -1;
}
if (write(fd, data, size) != size) {
perror("i2c write failed");
return -1;
}
return 0;
}
2.3. 接收数据
#include <unistd.h>
int i2c_receive(int fd, uint8_t slave_address, uint8_t *data, int size) {
uint8_t cmd[2];
cmd[0] = slave_address;
cmd[1] = I2C_READ;
if (write(fd, cmd, 2) != 2) {
perror("i2c send start failed");
return -1;
}
if (read(fd, data, size) != size) {
perror("i2c read failed");
return -1;
}
return 0;
}
3. SPI通信库函数
3.1. SPI初始化
#include <fcntl.h>
#include <unistd.h>
#include <linux/spi/spidev.h>
#include <stdint.h>
#include <string.h>
#include <sys/ioctl.h>
int spi_init(int dev, int mode, int bits, int speed) {
int ret = 0;
int fd = open("/dev/spidev0.0", O_RDWR);
if (fd < 0) {
perror("Could not open device");
return -1;
}
struct spi_ioc_transfer tr = {
.tx_buf = (uintptr_t)&tx[0],
.rx_buf = (uintptr_t)&rx[0],
.len = 1,
.speed_hz = speed,
.delay_usecs = 0,
.mode = mode,
.bits_per_word = bits
};
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 0) {
perror("SPI_IOC_MESSAGE");
return -1;
}
close(fd);
return 0;
}
3.2. 发送数据
#include <fcntl.h>
#include <unistd.h>
#include <linux/spi/spidev.h>
#include <stdint.h>
#include <string.h>
#include <sys/ioctl.h>
int spi_send(int fd, const uint8_t *tx, uint8_t *rx, int len) {
struct spi_ioc_transfer tr = {
.tx_buf = (uintptr_t)tx,
.rx_buf = (uintptr_t)rx,
.len = len,
.speed_hz = 1000000,
.delay_usecs = 0,
.mode = 0,
.bits_per_word = 8
};
return ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
}
3.3. 接收数据
#include <fcntl.h>
#include <unistd.h>
#include <linux/spi/spidev.h>
#include <stdint.h>
#include <string.h>
#include <sys/ioctl.h>
int spi_receive(int fd, uint8_t *rx, int len) {
struct spi_ioc_transfer tr = {
.tx_buf = (uintptr_t)NULL,
.rx_buf = (uintptr_t)rx,
.len = len,
.speed_hz = 1000000,
.delay_usecs = 0,
.mode = 0,
.bits_per_word = 8
};
return ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
}
总结
掌握这些常用的硬件编程库函数,可以帮助我们更好地控制硬件设备,实现各种功能。当然,实际开发过程中还需要根据具体的硬件平台和需求,选择合适的库和开发工具。希望本文能对您有所帮助。
