基于STM32f407ZGT6和TCS3200的颜色采集,并利用串口通信至matlab中实现颜色识别(HAL库)

假期学校是实践题目,实现的功能如标题。
使用的普中开发板,有详细的传感器资料,matlab部分主要是依靠网络上的资料。

一、引言

tcs3200传感器的原理网上有很多,主要讲一下思路:

  1. 单片机设置一个外部触发中断和内部定时器中断;
  2. 传感器发送方波至单片机,每来一次上升沿,中断回调函数触发一次,计数加一;
  3. 定时器回调函数每50ms读取一次count值并清零;
  4. 白平衡;
  5. matlab读取串口传输的数据,并通过GUI界面显示颜色。

二、cubeMX配置引脚:

在这里插入图片描述
在这里插入图片描述
PA0–TIM2_CH1
其余都是GPIO_Output
在这里插入图片描述
TIM2的通道1做外部触发,上升沿到来触发一次
在这里插入图片描述
TIM6做内部定时器,我单片机设置的是72MHz,50ms=(7200*500)/70M
在这里插入图片描述
通信串口用的usart1,波特率115200
在这里插入图片描述
各引脚的状态配置如上
在这里插入图片描述
打开定时器、外部中断、通信接口的中断

在这里插入图片描述
RCC设置为外部晶振
在这里插入图片描述
sys设置为serial wire,否则后续在keil中可能无法调试
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三、keil配置

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
外加子文件的话记得添加路径
在这里插入图片描述
点setting后进入下面的界面,设置成SW,即前面配置时对应的sys中的serial wire
在这里插入图片描述

四、代码:

main.c

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"

/* USER CODE BEGIN Includes */
#include "system.h"
#include "SysTick.h"
#include "key.h"
#include "exti.h"
#include "stm32f4xx_it.h"
/* USER CODE END Includes */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
float RGB_Scale[3];          //数组存储3个RGB比例因子
int count = 0;               //统计脉冲数
int cnt[3];                  //数组存储RGB三种颜色的脉冲值
int flag=0;                  //滤波器选择模式标志
int white_balance=0;
/* USER CODE END PD */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void filter(int s2,int s3)   //滤波器模式选择函数,根据S2和S3的电位来选择红、绿、蓝、三种颜色的滤波器
{
    if(s2==0&&s3==0)
			{PCout(2)=0;PCout(3)=0;}
    if(s2==0&&s3==1)
			{PCout(2)=0;PCout(3)=1;}
    if(s2==1&&s3==0)
			{PCout(2)=1;PCout(3)=0;}
    if(s2==1&&s3==1)
			{PCout(2)=1;PCout(3)=1;}			
}
void TSC_WB(int s2, int s3)  //结束上一种颜色识别,开始下一种颜色的识别 
{
  count = 0;                 //统计脉冲值清零
  flag ++;                   //输出信号计数标志+1,进行下一个颜色的脉冲统计
  filter(s2, s3);            //选择滤波器模式
}
/* USER CODE END 0 */
/**
 1. @brief  The application entry point.
 2. @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
	u8 key,i=0;
  /* USER CODE END 1 */
  /* MCU Configuration--------------------------------------------------------*/
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
  /* USER CODE BEGIN Init */
	SysTick_Init(168);
  /* USER CODE END Init */
  /* Configure the system clock */
  SystemClock_Config();
  /* USER CODE BEGIN SysInit */
  /* USER CODE END SysInit */
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_TIM6_Init();
  MX_TIM2_Init();
  /* USER CODE BEGIN 2 */
	HAL_TIM_Base_Start_IT(&htim2);
	HAL_TIM_Base_Start_IT(&htim6);          //使能TIM6
	PCout(0)=0;PCout(1)=1;                  //2%的输出比例因子
	PAout(1)=1;                             //打开白光LED
  /* USER CODE END 2 */
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
		key=KEY_Scan(1);
		switch(key)
		{
			case KEY0_PRESS:white_balance=0;break;               //停止检测
			case KEY1_PRESS:white_balance=1;break;               //白平衡
			case KEY2_PRESS:white_balance=2;break;               //检测
		}
	}
  /* USER CODE END 3 */
}
/* USER CODE BEGIN 4 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//50ms一次
	{
		if(htim->Instance == htim6.Instance){
			count = __HAL_TIM_GET_COUNTER(&htim2);               //记脉冲数
			if(white_balance==1){                                //白平衡
				switch(flag){
					 case 0:
							TSC_WB(0,0);                                 //让红色光线通过滤波器
							break;
					 case 1:
							cnt[0] = count;                    					 //存储50ms内的红光通过滤波器时脉冲个数
							RGB_Scale[0] = 255.0/ cnt[0];                //红色光比例因子
							TSC_WB(1,1);                                 //选择让绿色光线通过滤波器的模式
							break;
					 case 2:
							cnt[1] = count;                              //存储50ms内的绿光通过滤波器时脉冲个数
							RGB_Scale[1] = 255.0/ cnt[1] ;               //绿色光比例因子
							TSC_WB(0,1);                                 //选择让蓝色光线通过滤波器的模式
							break;
					 case 3:
							cnt[2] = count;                              //存储50ms内的蓝光通过滤波器时脉冲个数
							RGB_Scale[2] = 255.0/ cnt[2] ;               //蓝色光比例因子
							TSC_WB(1,0);                                 //选择无滤波器的模式
							white_balance=0;
							flag=0;
							break;}
					LED1=!LED1;
					TIM2->CNT=0;
					if(white_balance==0){
						printf("%d  ",(int)(cnt[0]*RGB_Scale[0]));
						printf("%d  ",(int)(cnt[1]*RGB_Scale[1]));
						printf("%d  \n",(int)(cnt[2]*RGB_Scale[2]));}}
			else if(white_balance==2)                            //检测模式
			{   
				switch(flag){
					 case 0:
							TSC_WB(0, 0);                                //选择让红色光线通过滤波器的模式
							break;
					 case 1:
							cnt[0] = count;                              //存储50ms内的红光通过滤波器时,TCS3200输出的脉冲个数
							int R=cnt[0]*RGB_Scale[0];
							if(R>255) R=255;
							TSC_WB(1, 1);                                //选择让绿色光线通过滤波器的模式
							break;
					 case 2:
							cnt[1] = count;                              //存储50ms内的绿光通过滤波器时,TCS3200输出的脉冲个数
							int G=cnt[1]*RGB_Scale[1];
							if(G>255) G=255;
							TSC_WB(0, 1);                                //选择让蓝色光线通过滤波器的模式
							break;
					 case 3:
							cnt[2] = count;                              //存储50ms内的蓝光通过滤波器时,TCS3200输出的脉冲个数
							int B=cnt[2]*RGB_Scale[2];
							if(B>255) B=255;
							TSC_WB(1, 0);                                //选择无滤波器的模式
							white_balance=0;
							flag=0;
							break;}
				LED2=!LED2;                                        //DS1灯
				TIM2->CNT=0;
				if(white_balance==0){
						printf("%d  ",(int)(cnt[0]*RGB_Scale[0]));
						printf("%d  ",(int)(cnt[1]*RGB_Scale[1]));
						printf("%d  \n",(int)(cnt[2]*RGB_Scale[2]));}
			}
			else {}                                              //空载
	}
}
/* USER CODE END 4 */

matlab代码

function pushbutton1_Callback(hObject, eventdata, handles)
global R G B
s=serial('com3');
set(s,'BaudRate', 115200,'DataBits',8,'Parity','none');
s.DataTerminalReady='off';
fclose(instrfind); 
fopen(s);
a=fscanf(s,'%d');
fclose(s);
fprintf('%c',a);
R=a(1,1)
G=a(2,1)
B=a(3,1)
set(handles.edit2,'string',num2str(R));
set(handles.edit3,'string',num2str(G));
set(handles.edit4,'string',num2str(B));

上述代码实现的是打开串口,接受串口发送的数据保存成数组3*1的数组,读取数组
这之后是将RGB转换成HSV,这部分不是我做的不大了解了,但好像就是if else的判断确定色域,网上应该有不少这方面的参考代码

五、参考资料

1.外部中断:https://blog.csdn.net/qq_45607873/article/details/124633942
2.基于stm32f103的颜色识别,写的很好,有原理什么的,我主要参考的这个博客:https://blog.csdn.net/weixin_50950634/article/details/114645247?
3.MATLAB App Designer 特别篇:RGB颜色提取器(据说是比GUI先进的工具,参考学习):https://blog.csdn.net/slandarer/article/details/115035583
4.matlab GUI编写串口助手:https://bbs.elecfans.com/jishu_1872177_1_1.html
5.matlabGUI串口助手的文件,文件不好使了,但是是很好的参考资料,可以用来学习:https://download.csdn.net/download/zhufenghao/7359223?

  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值