使用Maix Bit的摄像头、SD卡、文件系统和LCD实现一个简易的照相机。使用BOOT按键进行拍照,之后将照片存储在SD卡上面。
SPI and DMAC usage:
SPI0 - LCD
SPI1 - SD card
SPI2 - unused
SPI3 - Flash
DMAC Channel 0 - LCD
DMAC Channel 1 - SD card
1、代码获取
在我前面一篇博客里面简述了代码如何下载以及使用。https://blog.csdn.net/weixin_45488643/article/details/109990336如有需要自行查看。
2、代码修改
首先自己先创建一个新的工程文件,然后将dvp2sdcard文件夹下面的代码复制到自己创建的文件夹下面:
安装依赖库文件:
比较重要的一点,开启控制:
打开board_config.h 我自己使用的是Maix bit 开发板,所以选择如下配置文件,根据需要选择自己的开发板硬件配置。
3、API简介
LCD、SD和文件系统的常用API前面的博客已经介绍过了,如有兴趣,自行查看。
3.1 图片转化保存
int rgb565tobmp(uint8_t *buf,int width,int height, const char *filename)
*buf 保存的数据; width、height图片大小;*filename图片保存路径
3.2 内存释放
void iomem_free(void *paddr)
*paddr 空间地址
4 、代码修改
使用标志来保存数据。
static uint32_t NUM = 0;
char buf[80];
目前可以保存9999张照片,保存更多自行修改。
4.1 主函数代码
#include <stdio.h>
#include <string.h>
#include "board_config.h"
#include "dvp.h"
#include "ff.h"
#include "fpioa.h"
#include "gpiohs.h"
#include "iomem.h"
#include "lcd.h"
#include "nt35310.h"
#include "ov2640.h"
#include "ov5640.h"
#include "plic.h"
#include "rgb2bmp.h"
#include "sdcard.h"
#include "sysctl.h"
#include "uarths.h"
/* SPI and DMAC usage
*
* SPI0 - LCD
* SPI1 - SD card
* SPI2 - unused
* SPI3 - Flash
*
* DMAC Channel 0 - LCD
* DMAC Channel 1 - SD card
*
*/
#define KEY_GPIONUM 0
uint32_t *g_lcd_gram0;
uint32_t *g_lcd_gram1;
volatile uint8_t g_dvp_finish_flag;
volatile uint8_t g_ram_mux;
volatile uint8_t g_save_flag;
void irq_key(void *gp) { g_save_flag = 1; }
static int on_irq_dvp(void *ctx) {
if (dvp_get_interrupt(DVP_STS_FRAME_FINISH)) {
/* switch gram */
dvp_set_display_addr(g_ram_mux ? (uint32_t)g_lcd_gram0
: (uint32_t)g_lcd_gram1);
dvp_clear_interrupt(DVP_STS_FRAME_FINISH);
g_dvp_finish_flag = 1;
} else {
if (g_dvp_finish_flag == 0) dvp_start_convert();
dvp_clear_interrupt(DVP_STS_FRAME_START);
}
return 0;
}
static void io_mux_init(void) {
#if BOARD_LICHEEDAN
/* SD card */
fpioa_set_function(27, FUNC_SPI1_SCLK);
fpioa_set_function(28, FUNC_SPI1_D0);
fpioa_set_function(26, FUNC_SPI1_D1);
fpioa_set_function(29, FUNC_GPIOHS7);
/* Init DVP IO map and function settings */
fpioa_set_function(42, FUNC_CMOS_RST);
fpioa_set_function(44, FUNC_CMOS_PWDN);
fpioa_set_function(46, FUNC_CMOS_XCLK);
fpioa_set_function(43, FUNC_CMOS_VSYNC);
fpioa_set_function(45, FUNC_CMOS_HREF);
fpioa_set_function(47, FUNC_CMOS_PCLK);
fpioa_set_function(41, FUNC_SCCB_SCLK);
fpioa_set_function(40, FUNC_SCCB_SDA);
/* Init SPI IO map and function settings */
fpioa_set_function(38, FUNC_GPIOHS0 + DCX_GPIONUM);
fpioa_set_function(36, FUNC_SPI0_SS3);
fpioa_set_function(39, FUNC_SPI0_SCLK);
fpioa_set_function(37, FUNC_GPIOHS0 + RST_GPIONUM);
sysctl_set_spi0_dvp_data(1);
fpioa_set_function(16, FUNC_GPIOHS0 + KEY_GPIONUM);
#else
/* SD card */
fpioa_set_function(29, FUNC_SPI1_SCLK);
fpioa_set_function(30, FUNC_SPI1_D0);
fpioa_set_function(31, FUNC_SPI1_D1);
fpioa_set_function(32, FUNC_GPIOHS7);
/* Init DVP IO map and function settings */
fpioa_set_function(11, FUNC_CMOS_RST);
fpioa_set_function(13, FUNC_CMOS_PWDN);
fpioa_set_function(14, FUNC_CMOS_XCLK);
fpioa_set_function(12, FUNC_CMOS_VSYNC);
fpioa_set_function(17, FUNC_CMOS_HREF);
fpioa_set_function(15, FUNC_CMOS_PCLK);
fpioa_set_function(10, FUNC_SCCB_SCLK);
fpioa_set_function(9, FUNC_SCCB_SDA);
/* Init SPI IO map and function settings */
fpioa_set_function(8, FUNC_GPIOHS0 + DCX_GPIONUM);
fpioa_set_function(6, FUNC_SPI0_SS3);
fpioa_set_function(7, FUNC_SPI0_SCLK);
sysctl_set_spi0_dvp_data(1);
fpioa_set_function(26, FUNC_GPIOHS0 + KEY_GPIONUM);
#endif
}
static void io_set_power(void) {
#if BOARD_LICHEEDAN
/* Set dvp and spi pin to 1.8V */
sysctl_set_power_mode(SYSCTL_POWER_BANK6, SYSCTL_POWER_V18);
sysctl_set_power_mode(SYSCTL_POWER_BANK7, SYSCTL_POWER_V18);
#else
/* Set dvp and spi pin to 1.8V */
sysctl_set_power_mode(SYSCTL_POWER_BANK1, SYSCTL_POWER_V18);
sysctl_set_power_mode(SYSCTL_POWER_BANK2, SYSCTL_POWER_V18);
#endif
}
int main(void) {
FATFS sdcard_fs;
static uint32_t NUM = 0;
char buf[80];
/* Set CPU and dvp clk */
sysctl_pll_set_freq(SYSCTL_PLL0, 800000000UL);
uarths_init();
io_mux_init();
io_set_power();
plic_init();
gpiohs_set_drive_mode(KEY_GPIONUM, GPIO_DM_INPUT);
gpiohs_set_pin_edge(KEY_GPIONUM, GPIO_PE_FALLING);
gpiohs_set_irq(KEY_GPIONUM, 2, irq_key);
/* LCD init */
printf("LCD init\n");
lcd_init();
#if BOARD_LICHEEDAN
#if OV5640
lcd_set_direction(DIR_YX_LRDU);
#else
lcd_set_direction(DIR_YX_RLDU); // DIR_YX_RLDU DIR_YX_LRDU
#endif
#else
#if OV5640
lcd_set_direction(DIR_YX_LRUD);
#else
lcd_set_direction(DIR_YX_LRUD);
#endif
#endif
lcd_clear(BLACK);
g_lcd_gram0 = (uint32_t *)iomem_malloc(320 * 240 * 2);
g_lcd_gram1 = (uint32_t *)iomem_malloc(320 * 240 * 2);
/* DVP init */
printf("DVP init\n");
#if OV5640
dvp_init(16);
dvp_set_xclk_rate(50000000);
dvp_enable_burst();
dvp_set_output_enable(0, 0);
dvp_set_output_enable(1, 1);
dvp_set_image_format(DVP_CFG_RGB_FORMAT);
dvp_set_image_size(320, 240);
ov5640_init();
#else
dvp_init(8);
dvp_set_xclk_rate(24000000);
dvp_enable_burst();
dvp_set_output_enable(0, 0);
dvp_set_output_enable(1, 1);
dvp_set_image_format(DVP_CFG_RGB_FORMAT);
dvp_set_image_size(320, 240);
ov2640_init();
#endif
dvp_set_display_addr((uint32_t)g_lcd_gram0);
dvp_config_interrupt(DVP_CFG_START_INT_ENABLE | DVP_CFG_FINISH_INT_ENABLE, 0);
dvp_disable_auto();
/* DVP interrupt config */
printf("DVP interrupt config\n");
plic_set_priority(IRQN_DVP_INTERRUPT, 1);
plic_irq_register(IRQN_DVP_INTERRUPT, on_irq_dvp, NULL);
plic_irq_enable(IRQN_DVP_INTERRUPT);
/* enable global interrupt */
sysctl_enable_irq();
/* SD card init */
if (sd_init()) {
printf("Fail to init SD card\n");
return -1;
}
/* mount file system to SD card */
if (f_mount(&sdcard_fs, _T("0:"), 1)) {
printf("Fail to mount file system\n");
return -1;
}
/* system start */
printf("system start\n");
g_ram_mux = 0;
g_dvp_finish_flag = 0;
dvp_clear_interrupt(DVP_STS_FRAME_START | DVP_STS_FRAME_FINISH);
dvp_config_interrupt(DVP_CFG_START_INT_ENABLE | DVP_CFG_FINISH_INT_ENABLE, 1);
while (1) {
/* ai cal finish*/
while (g_dvp_finish_flag == 0)
;
g_ram_mux ^= 0x01;
g_dvp_finish_flag = 0;
if (g_save_flag) {
sprintf(buf, "%dphoto.bmp", NUM++);
rgb565tobmp((uint8_t *)(g_ram_mux ? g_lcd_gram0 : g_lcd_gram1), 320, 240,
_T(buf)); //文件保存名字
g_save_flag = 0;
if (NUM == 9999) {
NUM = 0;
}
}
/* display pic*/
lcd_draw_picture(0, 0, 320, 240, g_ram_mux ? g_lcd_gram0 : g_lcd_gram1);
}
iomem_free(g_lcd_gram0); //释放内存
iomem_free(g_lcd_gram1);
return 0;
}