/* * 自然写智能点阵笔嵌入式固件软件 V1.0 * camera_driver.c - CMOS摄像头传感器驱动 * * 功能说明: * 1. CMOS图像传感器SPI通信驱动 * 2. 传感器寄存器配置(曝光、增益、帧率) * 3. 图像采集触发与数据读取 * 4. 传感器电源管理(开/关/低功耗) * 5. 自检与故障检测 */ #include #include #include #include "hal_spi.h" #include "hal_gpio.h" /* ========== 传感器寄存器地址 ========== */ /* 芯片ID寄存器(只读) */ #define REG_CHIP_ID 0x00 /* 系统控制寄存器 */ #define REG_SYS_CTRL 0x01 #define SYS_CTRL_RESET 0x80 /* 软复位 */ #define SYS_CTRL_SLEEP 0x40 /* 睡眠模式 */ #define SYS_CTRL_ENABLE 0x01 /* 使能采集 */ /* 曝光时间寄存器(高/低字节) */ #define REG_EXPOSURE_H 0x02 #define REG_EXPOSURE_L 0x03 /* 模拟增益寄存器 */ #define REG_GAIN 0x04 /* 帧率控制寄存器 */ #define REG_FRAME_RATE 0x05 /* 像素数据起始寄存器(读取时自动递增) */ #define REG_PIXEL_DATA 0x10 /* 帧就绪状态位 */ #define REG_STATUS 0x0F #define STATUS_FRAME_READY 0x01 /* 预期芯片ID值 */ #define EXPECTED_CHIP_ID 0xA5 /* ========== 传感器模式枚举 ========== */ #define CAMERA_MODE_SINGLE 0 /* 单帧模式 */ #define CAMERA_MODE_CONTINUOUS 1 /* 连续帧模式 */ /* ========== GPIO引脚定义 ========== */ #define GPIO_CAMERA_POWER 12 /* 传感器电源控制引脚 */ #define GPIO_CAMERA_CS 15 /* SPI片选引脚 */ #define GPIO_CAMERA_LED 16 /* 红外LED照明引脚 */ /* ========== SPI通信 ========== */ /* SPI端口号 */ #define CAMERA_SPI_PORT SPI_PORT_1 /* 读寄存器标志位 */ #define SPI_READ_FLAG 0x80 /* ========== 静态变量 ========== */ /* 传感器是否已初始化 */ static bool s_camera_initialized = false; /* 传感器是否已上电 */ static bool s_camera_powered = false; /* 当前工作模式 */ static uint8_t s_camera_mode = CAMERA_MODE_SINGLE; /* ========== SPI底层读写 ========== */ /** * SPI写单个寄存器 * @param reg_addr 寄存器地址(7位) * @param value 写入值 */ static void camera_write_reg(uint8_t reg_addr, uint8_t value) { uint8_t tx[2]; tx[0] = reg_addr & 0x7F; /* 最高位0=写操作 */ tx[1] = value; hal_gpio_write(GPIO_CAMERA_CS, 0); /* 拉低CS */ hal_spi_transfer(CAMERA_SPI_PORT, tx, NULL, 2); hal_gpio_write(GPIO_CAMERA_CS, 1); /* 拉高CS */ } /** * SPI读单个寄存器 * @param reg_addr 寄存器地址 * @return 读取的值 */ static uint8_t camera_read_reg(uint8_t reg_addr) { uint8_t tx[2], rx[2]; tx[0] = reg_addr | SPI_READ_FLAG; /* 最高位1=读操作 */ tx[1] = 0x00; /* 空字节用于接收数据 */ hal_gpio_write(GPIO_CAMERA_CS, 0); hal_spi_transfer(CAMERA_SPI_PORT, tx, rx, 2); hal_gpio_write(GPIO_CAMERA_CS, 1); return rx[1]; } /** * SPI批量读取像素数据 * 使用DMA方式高速读取整帧图像数据 * * @param buffer 接收缓冲区 * @param length 读取字节数 */ static void camera_read_pixels(uint8_t *buffer, uint16_t length) { uint8_t cmd = REG_PIXEL_DATA | SPI_READ_FLAG; hal_gpio_write(GPIO_CAMERA_CS, 0); /* 先发送寄存器地址 */ hal_spi_transfer(CAMERA_SPI_PORT, &cmd, NULL, 1); /* 然后连续读取像素数据 */ hal_spi_receive(CAMERA_SPI_PORT, buffer, length); hal_gpio_write(GPIO_CAMERA_CS, 1); } /* ========== 传感器初始化 ========== */ /** * 初始化CMOS图像传感器 * 配置GPIO、验证芯片ID、设置初始参数 * * @return 0成功, -1芯片ID错误, -2通信失败 */ int camera_driver_init(void) { /* 配置控制GPIO为输出 */ hal_gpio_config_output(GPIO_CAMERA_POWER); hal_gpio_config_output(GPIO_CAMERA_CS); hal_gpio_config_output(GPIO_CAMERA_LED); /* CS默认高电平(不选中) */ hal_gpio_write(GPIO_CAMERA_CS, 1); /* 上电 */ hal_gpio_write(GPIO_CAMERA_POWER, 1); s_camera_powered = true; /* 等待传感器启动(典型10ms) */ for (volatile int i = 0; i < 100000; i++); /* 软复位 */ camera_write_reg(REG_SYS_CTRL, SYS_CTRL_RESET); for (volatile int i = 0; i < 50000; i++); /* 验证芯片ID */ uint8_t chip_id = camera_read_reg(REG_CHIP_ID); if (chip_id != EXPECTED_CHIP_ID) { s_camera_initialized = false; return -1; } /* 设置默认参数 */ camera_write_reg(REG_EXPOSURE_H, 0x00); camera_write_reg(REG_EXPOSURE_L, 0x80); /* 曝光值128 */ camera_write_reg(REG_GAIN, 0x40); /* 增益64 */ camera_write_reg(REG_FRAME_RATE, 100); /* 100Hz帧率 */ /* 使能传感器 */ camera_write_reg(REG_SYS_CTRL, SYS_CTRL_ENABLE); s_camera_initialized = true; return 0; } /* ========== 参数配置 ========== */ /** * 设置曝光时间 * @param exposure 曝光值(0-255,映射到传感器实际曝光时间) */ void camera_set_exposure(uint8_t exposure) { if (!s_camera_initialized) return; camera_write_reg(REG_EXPOSURE_H, 0x00); camera_write_reg(REG_EXPOSURE_L, exposure); } /** * 设置模拟增益 * @param gain 增益值(0-255) */ void camera_set_gain(uint8_t gain) { if (!s_camera_initialized) return; camera_write_reg(REG_GAIN, gain); } /** * 设置工作模式 * @param mode CAMERA_MODE_SINGLE 或 CAMERA_MODE_CONTINUOUS */ void camera_set_mode(uint8_t mode) { s_camera_mode = mode; } /* ========== 图像采集 ========== */ /** * 触发单帧采集 * 在连续模式下,传感器会自动拍摄 * 在单帧模式下,需要每次手动触发 */ void camera_trigger_capture(void) { if (!s_camera_initialized || !s_camera_powered) return; if (s_camera_mode == CAMERA_MODE_SINGLE) { /* 单帧模式:写触发位 */ uint8_t ctrl = camera_read_reg(REG_SYS_CTRL); camera_write_reg(REG_SYS_CTRL, ctrl | 0x02); } /* 开启红外LED照明(点阵图案需要红外光照射才能看到) */ hal_gpio_write(GPIO_CAMERA_LED, 1); } /** * 等待帧就绪 * @param timeout_ms 超时毫秒数 * @return true帧已就绪, false超时 */ bool camera_wait_frame_ready(uint16_t timeout_ms) { uint16_t elapsed = 0; while (elapsed < timeout_ms) { uint8_t status = camera_read_reg(REG_STATUS); if (status & STATUS_FRAME_READY) { return true; } /* 简单延时 */ for (volatile int i = 0; i < 1000; i++); elapsed++; } return false; } /** * 获取传感器数据寄存器地址(用于DMA配置) */ uint32_t camera_get_data_register(void) { /* 返回SPI数据寄存器的内存映射地址 */ return hal_spi_get_data_addr(CAMERA_SPI_PORT); } /* ========== 电源管理 ========== */ /** * 传感器上电 */ void camera_power_on(void) { if (s_camera_powered) return; hal_gpio_write(GPIO_CAMERA_POWER, 1); s_camera_powered = true; /* 等待传感器稳定 */ for (volatile int i = 0; i < 100000; i++); /* 重新使能 */ camera_write_reg(REG_SYS_CTRL, SYS_CTRL_ENABLE); } /** * 传感器断电(最低功耗) */ void camera_power_off(void) { if (!s_camera_powered) return; /* 关闭红外LED */ hal_gpio_write(GPIO_CAMERA_LED, 0); /* 传感器进入睡眠 */ camera_write_reg(REG_SYS_CTRL, SYS_CTRL_SLEEP); /* 切断电源 */ hal_gpio_write(GPIO_CAMERA_POWER, 0); s_camera_powered = false; } /** * 传感器自检 * 检查SPI通信是否正常、芯片ID是否正确 * * @return 0正常, -1通信故障, -2芯片ID异常 */ int camera_self_test(void) { if (!s_camera_powered) { return -1; } uint8_t chip_id = camera_read_reg(REG_CHIP_ID); if (chip_id != EXPECTED_CHIP_ID) { return -2; } /* 写读测试:写入一个可写寄存器并读回验证 */ uint8_t test_val = 0x55; camera_write_reg(REG_GAIN, test_val); uint8_t read_back = camera_read_reg(REG_GAIN); if (read_back != test_val) { return -1; } /* 恢复原始增益值 */ camera_write_reg(REG_GAIN, 0x40); return 0; }