冻鱼
⚒去学习,去奋斗,去劳动⚒
iSTHMUS BLOG

MM32SPIN27PS 逐飞库使用日志 -1

MM32SPIN27PS   逐飞库使用日志 -1

上手mm32spin27ps逐飞封装库已经有大概快一个星期了,目前还在逐渐熟悉函数的具体使用,通过实际使用这些函数来发现其中的问题,或者说自身对其中一些内容的误解。之所以之前一直没写日志,是因为基本上没遇见什么问题。今天(其实是昨天,现在凌晨了都),在写MT9V032的时候出现了一些尚未解决的问题,所以先做记录,以便后续解决。

文章中部分源码引用声明:

/*********************************************************************************************************************
* COPYRIGHT NOTICE
* Copyright (c) 2018,逐飞科技
* All rights reserved.
* 技术讨论QQ群:一群:179029047(已满)  二群:244861897
*
* 以下所有内容版权均属逐飞科技所有,未经允许不得用于商业用途,
* 欢迎各位使用并传播本程序,修改内容时必须保留逐飞科技的版权声明。
*
* @file				SEEKFREE_MT9V03X
* @company			成都逐飞科技有限公司
* @author			逐飞科技(QQ3184284598)
* @version			查看doc内version文件 版本说明
* @Software			IAR 8.3 or MDK 5.24
* @Taobao			https://seekfree.taobao.com/
* @date				2020-11-23
********************************************************************************************************************/

SEEKFREE_MT9V032库函数:

//-------------------------------------------------------------------------------------------------------------------
// @brief		MT9V03X摄像头串口中断函数
// @param		NULL
// @return		void
// @since		v1.0
// Sample usage:
// @note
//-------------------------------------------------------------------------------------------------------------------
void mt9v03x_uart_callback(void)
//-------------------------------------------------------------------------------------------------------------------
// @brief		配置摄像头内部配置信息
// @param		uartn			选择使用的串口
// @param		buff			发送配置信息的地址
// @return		void
// @since		v1.0
// Sample usage:				调用该函数前请先初始化串口
//-------------------------------------------------------------------------------------------------------------------
void set_config(UARTN_enum uartn, int16 buff[CONFIG_FINISH-1][2])
//-------------------------------------------------------------------------------------------------------------------
// @brief		获取摄像头内部配置信息
// @param		uartn			选择使用的串口
// @param		buff			接收配置信息的地址
// @return		void
// @since		v1.0
// Sample usage:				调用该函数前请先初始化串口
//-------------------------------------------------------------------------------------------------------------------
void get_config(UARTN_enum uartn, int16 buff[CONFIG_FINISH-1][2])
//-------------------------------------------------------------------------------------------------------------------
// @brief		获取摄像头固件版本
// @param		uartn			选择使用的串口
// @return		void
// @since		v1.0
// Sample usage:				调用该函数前请先初始化串口
//-------------------------------------------------------------------------------------------------------------------
uint16 get_version(UARTN_enum uartn)
//-------------------------------------------------------------------------------------------------------------------
// @brief		单独设置摄像头曝光时间
// @param		uartn			选择使用的串口
// @param		light			设置曝光时间越大图像越亮,摄像头收到后会根据分辨率及FPS计算最大曝光时间如果设置的数据过大,那么摄像头将会设置这个最大值
// @return		uint16			当前曝光值,用于确认是否正确写入
// @since		v1.0
// Sample usage:				调用该函数前请先初始化串口
//-------------------------------------------------------------------------------------------------------------------
uint16 set_exposure_time(UARTN_enum uartn, uint16 light)
//-------------------------------------------------------------------------------------------------------------------
// @brief		对摄像头内部寄存器进行写操作
// @param		uartn			选择使用的串口
// @param		addr			摄像头内部寄存器地址
// @param		data			需要写入的数据
// @return		uint16			寄存器当前数据,用于确认是否写入成功
// @since		v1.0
// Sample usage:				调用该函数前请先初始化串口
//-------------------------------------------------------------------------------------------------------------------
uint16 set_mt9v03x_reg(UARTN_enum uartn, uint8 addr, uint16 data)
//-------------------------------------------------------------------------------------------------------------------
// @brief		初始化摄像头场中断
// @param		NULL
// @return		void
// @since		v1.0
// Sample usage:
//-------------------------------------------------------------------------------------------------------------------
void mt9v03x_exti_init(void)
//-------------------------------------------------------------------------------------------------------------------
// @brief		初始化摄像头场PCLK输入
// @param		NULL
// @return		void
// @since		v1.0
// Sample usage:
//-------------------------------------------------------------------------------------------------------------------
void mt9v03x_tim1_etr_init(void)
//-------------------------------------------------------------------------------------------------------------------
// @brief		初始化摄像头场DMA
// @param		NULL
// @return		void
// @since		v1.0
// Sample usage:
//-------------------------------------------------------------------------------------------------------------------
void mt9v03x_dma_init(void)
//-------------------------------------------------------------------------------------------------------------------
// @brief		MT9V03X摄像头初始化
// @param		NULL
// @return		void
// @since		v1.0
// Sample usage:				使用FLEXIO接口采集摄像头
//-------------------------------------------------------------------------------------------------------------------
void mt9v03x_init(void)
//-------------------------------------------------------------------------------------------------------------------
// @brief		MT9V03X摄像头场中断
// @param		NULL
// @return		void
// @since		v1.0
// Sample usage:				在isr.c里面先创建对应的中断函数,然后调用该函数(之后别忘记清除中断标志位)
//-------------------------------------------------------------------------------------------------------------------
void mt9v03x_vsync(void)
//-------------------------------------------------------------------------------------------------------------------
// @brief		MT9V03X摄像头DMA完成中断
// @param		NULL
// @return		void
// @since		v1.0
// Sample usage:
//-------------------------------------------------------------------------------------------------------------------
void mt9v03x_dma(void)
//-------------------------------------------------------------------------------------------------------------------
// @brief		总钻风摄像头图像发送至上位机查看图像
// @param		uartn			使用的串口号
// @param		image			需要发送的图像地址
// @param		width			图像的列
// @param		height			图像的行
// @return		void
// @since		v1.0
// Sample usage:
//-------------------------------------------------------------------------------------------------------------------
void seekfree_sendimg_03x(UARTN_enum uartn, uint8 *image, uint16 width, uint16 height)

为啥贴这么多源码呢,我想是因为凑字数未来几天估计都要跟MT9V032纠缠,先贴这儿方便引用。

没啥内容的正文:

通览逐飞封装的所有函数,我想肯定刚开始不能直接莽取图像数组的那个函数,得先从小的开始。于是选择了get_version()这个函数,看起来是不是很简单?先初始化 UART2 然后使用已经做好映射的printf()函数直接打印到UART1。

然而作为一个倒霉蛋,我往往把事情想的过于简单。完成了上述工作后,rebuild并下载到flash,stlink设置了下载后自动复位,打开串口,却发现没有打印任何内容。

由于不会使用stlink进行硬件调试或者软件仿真,所以使用printf( )判断问题语句的传统方法,切实定位到是get_version()出错。下面贴一下该函数实现:

uint16 get_version(UARTN_enum uartn)
{
	uint16 temp;
	uint8  send_buffer[4];
	send_buffer[0] = 0xA5;
	send_buffer[1] = GET_STATUS;
	temp = GET_VERSION;
	send_buffer[2] = temp>>8;
	send_buffer[3] = (uint8)temp;
	uart_putbuff(uartn,send_buffer,4);
	while(!uart_receive_flag);    //最终确定卡在此处,只要确定为什么没有更新uart_receive_flag值即可
	uart_receive_flag = 0;
	return ((uint16)(receive[1]<<8) | receive[2]);

}

函数看起来还是很简洁的,简单判断可知唯一能够卡住的地方就是这个while循环。只要这个uart_receive_flag还是0,那就会一直困在这个while里,没有返回值,或者说根本不会运行到返回数据的步骤,也就很正常了。

所以解决这个问题,本质上只需要查明为什么uart_receive_flag没有更新就好了。

uart_receive_flag定义,可以看到:

static vuint8	uart_receive_flag;

哦豁,有个static关键字,也就是说在其修饰一个全局变量的时候,只能被该文件里的函数调用,那也就缩小了查找范围。

经过一番查找,发现唯一会改变uart_receive_flag标志位的仅有一个mt9v03x_uart_callback()函数(不算对该标志位进行复位的函数)

贴出其实现过程:

void mt9v03x_uart_callback(void)
{
	receive[receive_num] = (uart_index[MT9V03X_COF_UART])->RDR & 0x01FF;
	receive_num++;   //receive_num原值为0

	if(1==receive_num && 0XA5!=receive[0])  receive_num = 0;   
	if(3 == receive_num)
	{
		receive_num = 0;
		uart_receive_flag = 1;
	}
}

通过提供的MT9V032的手册,了解到这个0xA5是理论上读取的第一段数据(额忘了说,逐飞的MT9V032上有个用来配置参数的51,配置摄像头参数时实际上是和51通信,由51完成配置。这样就只需使用uart进行参数的配置而非IIC,非常简便)。

这里面有个RDR,挺有意思的,封装了两层最后还是读写寄存器...

https://blog.isthmus.tk:442/wp-content/uploads/2021/01/屏幕截图-2021-01-14-001203.png

对其进行与操作,然后取出数值存入数组。

看UM好像是说RDR是个缓冲区,UART接收到的数据暂存此处,溢出会由标志位标识,也就牵扯出另一个寄存器CSR:

https://blog.isthmus.tk:442/wp-content/uploads/2021/01/屏幕截图-2021-01-14-001409.png

1位上这个RXAVL应该就是起这个作用的...

所以我大致判断mt9v03x_uart_callback()这个函数使用的时候应该是需要重复调用,直到读到0xA5的数据头,再往下读三个数组元素,最后组成需要的数据。但是应该如何调用才能保证不会重复采集呢?也许就是通过CSR内的RXAVL位。今天在阅读程序的时候确有发现有函数有读取CSR的操作,不过当时未加注意,明天继续...

今日小结:

通体来说慢于预期进度,也大大低估了逐飞库的复杂程度。在排除错误方面,有相当大的一部分时间消耗在对硬件的排查上,毕竟自制学习板相当简陋,连VDD VCC都没有全部接上。此外,也没有很好的遵循单一变量的原则,常常因为求快,一次进行多项改动,对于排查错误往往是不利的。另外,调用函数时对参数检查不够,比如用于UART初始化的函数,代表RX和TX引脚的参数属于同一枚举类型,在使用时位置填反,编译器并不会有任何报错,耽误了很多时间。

遗留问题:

  1. 第一块自制学习板使用64 63脚(VDD和VSS)供电时无法下载程序,原因尚不清楚
  2. 使用第一份练习程序UART2发送数据时,所有发送的数据均和期望值存在差异,但使用重新建立的类似程序时,UART2发送数据正常,类似情况未复现。
  3. 正文中所述未完成内容

#Define

Author

翻车鱼就是本人了

Leave a Reply

textsms
account_circle
email

Comment moderation is enabled. Your comment may take some time to appear.

  • #DefineOwner

    :razz:

    1 month ago Reply
  • 勘误

    毕竟自制学习板相当简陋,连VDD VCC都没有全部接上。
    此处原想表达VSS和VDD
    (/ω\)

    5 months ago Reply

iSTHMUS BLOG

MM32SPIN27PS 逐飞库使用日志 -1
MM32SPIN27PS 逐飞库使用日志-1 ——对MT9V032模组的个人解读
Scan QR code to continue reading
2021-01-14