**使用注意事项:**因每次使用颜色识别的时候外界的光源条件都不相同,因此如果达到较好的使用效果,每次使用之前需要用白纸进行白平衡校准,这样工作起来更加方便。
经过资料可知TCS3200的工作原理是输出方波的频率,来判断颜色信号的强弱,资料百度文库链接:
Arduino:https://wenku.baidu.com/view/0b4d2a4376eeaeaad0f33044.html?from=search(以上链接有怎么设置输出比例因子的图表,通过S0,S1两个引脚的电平设置可以进行输出比例因子调整,见以下图表)
不同颜色采集的频率的设置方式:
89C51:https://wenku.baidu.com/view/488d2fb180eb6294dc886c04.html
模块工作时,通过两个可编程的引脚来动态选择所需要的滤波器,该传感器的典型输出频率范围从2Hz-500kHz,用户还可以通过两个可编程引脚来选择100%、20%或2%的输出比例因子。
经过调试发现,此模块一开始启动的时候最好先检测一张白色A4纸张,确定白平衡,然后在进行颜色判断,这样比较准确。
Excel的使用方法:按 Alt + 回车(Enter)组合键,光标后面的文字自动分成了两行,即按一次键,光标后的所有文字就会自动换行,不需一行行的重复按键。
以下代码是tcs3200.c文件中的:
#include “main.h”
#include “delay.h”
#include “gpio.h”
#include “tim.h”
u16 Rgena,Ggena,Bgena;//定义红、绿、蓝,三色因子
u16 Ramount,Gamount,Bamount;//具体的计算值
u16 amount;//采集到的频率
/duty是占空比/
extern uint32_t duty;
/freq是频率/
extern uint32_t freq;
extern uint32_t tmp1, tmp2;
/*****************************************
获取频率的函数
在定时器tim.c文件中已经配置完毕频率采集函数
在这可以直接进行使用
*****************************************/
u16 Get_amount(void)
{
if (tmp1 == 0)
{
duty = 0;//占空比复位
freq = 0;//频率复位
}
else
{
/占空比的计算公式/
duty = tmp2 * 100.0f / tmp1 + 0.5f;
/tmp1前后需要各加1,及tmp+2,以下输出结果为频率/
freq = 720000.0f / (tmp1+2);
}
return freq;
}
void tcs3200_init(u8 s0,u8 s1)
{
/S3 S3 IO 口初始化/
GPIO_ResetBits(GPIOC,GPIO_PIN_8);
GPIO_ResetBits(GPIOC,GPIO_PIN_9);
/S0 S1用来决定TCS3200输出的频率上限/
S0=s0;
S1=s1;
/*定时器1频率输入捕获中断开始*/
HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_1);
/*如果不需要占空比和频率数据就只开通道2即可。
第一次的数据是不正确的,实际工作中要将第一次的数据丢弃*/
HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_2);
}
/*******************************************
*
白平衡
*******************************************/
void whitebalance(void)
{
// EXTIX_Init(); //外部中断初始化
S2=0;S3=0;//红色通道
amount=0; //开始计数
delay_ms(10);
amount = Get_amount(); //求出频率
Rgena = amount; //求出红色因子
amount=0;
//----------------------------------
S2=1;S3=1;//绿色通道
amount=0;
delay_ms(10);
amount = Get_amount(); //求出频率
Ggena = amount; //求出绿色因子
amount=0;
//----------------------------------
S2=0;S3=1;//蓝色通道
amount=0;
delay_ms(10);
amount = Get_amount(); //求出频率
Bgena = amount;////求出蓝色因子
amount=0;
S2=1;S3=0;//关闭通道
}
u16 tcs3200_RED(void)
{
S2=0;S3=0;//模式设定为红色
amount=0;
delay_ms(10);
amount = Get_amount(); //求此时的频率数值
Ramount=(u32)amount*255/Rgena; //取R值
if(Ramount>255) Ramount = 255;
return Ramount;
// amount=0;
}
u16 tcs3200_GREEN(void)
{
S2=1;S3=1;//模式设定为绿色
amount=0;
delay_ms(10);
amount = Get_amount(); //求出此时的频率数值
Gamount=(u32)amount*255/Ggena; //取G值
if(Gamount>255) Gamount = 255;
return Gamount;
// amount=0;
}
u16 tcs3200_BLUE(void)
{
S2=0;S3=1;//模式设定为蓝色
amount=0;
delay_ms(10);
amount = Get_amount();//求出此时的频率
Bamount=(u32)amount*255/Bgena;//取B值
if(Bamount>255) Bamount = 255;
return Bamount;
// amount=0;
}
以下代码是tcs3200.h文件中的
#ifndef __TCS3200_H
#define __TCS3200_H
#include “sys.h”
extern u16 amount;
extern u16 Rgena,Ggena,Bgena;
extern u16 Ramount,Gamount,Bamount;
#define S0 PCout(6)
#define S1 PCout(7)
#define S2 PCout(8)
#define S3 PCout(9)
#define OUT PAin(8)
u16 Get_amount(void);
void tcs3200_init(u8 s0,u8 s1);
void whitebalance(void);
u16 tcs3200_RED(void);
u16 tcs3200_GREEN(void);
u16 tcs3200_BLUE(void);
#endif
以下是tim.c文件中的
#include “tim.h”
#include “gpio.h”
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
TIM_HandleTypeDef htim1;
TIM_HandleTypeDef htim4;
/* TIM1 init function */
void MX_TIM1_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_SlaveConfigTypeDef sSlaveConfig;
TIM_IC_InitTypeDef sConfigIC;
TIM_MasterConfigTypeDef sMasterConfig;
htim1.Instance = TIM1;
htim1.Init.Prescaler = 720-1;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 65535;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
{
_Error_Handler(FILE, LINE);
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
{
_Error_Handler(FILE, LINE);
}
if (HAL_TIM_IC_Init(&htim1) != HAL_OK)
{
_Error_Handler(FILE, LINE);
}
sSlaveConfig.SlaveMode = TIM_SLAVEMODE_RESET;
sSlaveConfig.InputTrigger = TIM_TS_TI1FP1;
sSlaveConfig.TriggerPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
sSlaveConfig.TriggerPrescaler = TIM_ICPSC_DIV1;
sSlaveConfig.TriggerFilter = 0;
if (HAL_TIM_SlaveConfigSynchronization(&htim1, &sSlaveConfig) != HAL_OK)
{
_Error_Handler(FILE, LINE);
}
sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
sConfigIC.ICFilter = 0;
if (HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC, TIM_CHANNEL_1) != HAL_OK)
{
_Error_Handler(FILE, LINE);
}
sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_FALLING;
sConfigIC.ICSelection = TIM_ICSELECTION_INDIRECTTI;
if (HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC, TIM_CHANNEL_2) != HAL_OK)
{
_Error_Handler(FILE, LINE);
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
{
_Error_Handler(FILE, LINE);
}
}
/* TIM4 init function */
void MX_TIM4_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_MasterConfigTypeDef sMasterConfig;
htim4.Instance = TIM4;
htim4.Init.Prescaler = 0;
htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
htim4.Init.Period = 0;
htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim4) != HAL_OK)
{
_Error_Handler(FILE, LINE);
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim4, &sClockSourceConfig) != HAL_OK)
{
_Error_Handler(FILE, LINE);
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK)
{
_Error_Handler(FILE, LINE);
}
}
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(tim_baseHandle->Instance==TIM1)
{
/* USER CODE BEGIN TIM1_MspInit 0 */
/* USER CODE END TIM1_MspInit 0 /
/ TIM1 clock enable */
__HAL_RCC_TIM1_CLK_ENABLE();
/**TIM1 GPIO Configuration
PA8 ------> TIM1_CH1
*/
GPIO_InitStruct.Pin = GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN TIM1_MspInit 1 */
/* USER CODE END TIM1_MspInit 1 /
}
else if(tim_baseHandle->Instance==TIM4)
{
/ USER CODE BEGIN TIM4_MspInit 0 */
/* USER CODE END TIM4_MspInit 0 /
/ TIM4 clock enable /
__HAL_RCC_TIM4_CLK_ENABLE();
/ USER CODE BEGIN TIM4_MspInit 1 */
/* USER CODE END TIM4_MspInit 1 */
}
}
void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)
{
if(tim_baseHandle->Instance==TIM1)
{
/* USER CODE BEGIN TIM1_MspDeInit 0 */
/* USER CODE END TIM1_MspDeInit 0 /
/ Peripheral clock disable */
__HAL_RCC_TIM1_CLK_DISABLE();
/**TIM1 GPIO Configuration
PA8 ------> TIM1_CH1
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_8);
/* TIM1 interrupt Deinit */
HAL_NVIC_DisableIRQ(TIM1_CC_IRQn);
/* USER CODE BEGIN TIM1_MspDeInit 1 */
/* USER CODE END TIM1_MspDeInit 1 /
}
else if(tim_baseHandle->Instance==TIM4)
{
/ USER CODE BEGIN TIM4_MspDeInit 0 */
/* USER CODE END TIM4_MspDeInit 0 /
/ Peripheral clock disable /
__HAL_RCC_TIM4_CLK_DISABLE();
/ USER CODE BEGIN TIM4_MspDeInit 1 */
/* USER CODE END TIM4_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
uint32_t duty = 0;
uint32_t freq = 0;
uint32_t tmp1 = 0, tmp2 = 0;
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef htim)//hal_tim.h回调函数
{
// volatile static uint32_t tmp1 = 0, tmp2 = 0;
/此例程只需要定时器输入捕获频率通道/
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{
tmp1 = HAL_TIM_ReadCapturedValue(&htim1, TIM_CHANNEL_1);//周期
}
/占空比可以不进行计算,计算也问题不大/
else if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
{
tmp2 = HAL_TIM_ReadCapturedValue(&htim1, TIM_CHANNEL_2);//占空比
}
}
//
/ USER CODE END 1 */
delay.c 中的配置:
#include “stm32f1xx_hal.h”
#include “tim.h”
#include “usart.h”
#include “sys.h”
#include “delay.h”
#include “stdio.h”
#include “stm32_hal_legacy.h”
u8 t=0,timer_second=0,timer_minute=0,timer_hour=0,timer_day=0,delayus_t=0;
//void timeclock_init(){
// HAL_TIM_Base_Start_IT(&htim2);
//}
void delay_init(){
__HAL_TIM_ENABLE(&htim4);
}
void delay_us(u32 nus){
__HAL_TIM_SetCounter(&htim4, 0);//htim17
while(__HAL_TIM_GetCounter(&htim4) < (36 * nus));//TIM4挂载在APB1的peripheral时钟线,时钟为36Mhz
__HAL_TIM_SetCounter(&htim4, 0);//htim17
while(__HAL_TIM_GetCounter(&htim4) < (36 * nus));//TIM4挂载在APB1的peripheral时钟线,时钟为36Mhz
return;
/* Disable the Peripheral */
}
Cube 的配置如下图所示: