这是业余选手人生中第一个单片机尝试,有任何建议请不吝指教🙇🏻♀️
需求
一个装置,用于测定物体颜色,读取RGB三个值,而且有白平衡功能
硬件
- STM32F103C8T6
- ST-Link
- TCS3200
- OLED显示屏
- 两个key
TCS3200接收外界光强信号输入STM32处理成RGB数值显示在OLED上
给两个key,一个白平衡,一个读数
ST-Link连电脑,keil5编程
S0-S3 —— PA0-PA3 推挽
LED —— PA4 推挽
OUT —— PA6 下拉
VCC —— ST-Link 5.0V
GND —— 负极
白平衡key —— B1
测定颜色key —— B11
原理
RGB颜色系统(纯理论,可跳过)
谈论物体的颜色,首先要理解RGB颜色系统,这是一种加色系统,但与美术三原色红黄蓝不同,而是以红绿蓝为三原色,R代表红色,G代表绿色,B代表蓝色,三个数值取值范围从0-255。物体颜色的本质就是其反射光与透射光的光强信息,而RGB的意义就是不同颜色光的强度,不同强度红绿蓝光信息被生物或电子感受器捕捉到并处理后,表现为能看到各种颜色。
在全暗的情况下RGB都为0,表现为黑色,全亮的情况下RGB都为255,表现为白色。一般条件下RGB三者中最高的一到两项决定物体的底色,比如R和B双高表现为紫色粉色,R单高表现为红色。
以上,只要我们获得一个物体反射、透射光对应的RGB值,就能系统地描述它的颜色。
白平衡(纯理论,可跳过)
不同环境中光强相差很大,物体颜色所对应的光强也在普遍随着环境整体光强改变,因此测定绝对光强相当于不考虑环境整体情况,对物体颜色的阐述反而是不准确的
但是在任何环境中,绝对的黑是不变的,即光强最小值为0,在变化的是特定环境下作为参考的白,即光强最大值随环境变化
白平衡就是在特定环境下定义什么样是“白色”,即各种颜色光强拉满的情况,然后才能执其两端用其中,使各种颜色的光强在黑白中间范围内找到对应的位置
TCS3200
如下图所示,模块中间有一个8x8的光电二极管方阵,其中各有16个格分别带有红色、绿色、蓝色的滤光片(还有16个格没有滤光片),用于接收不同颜色光强信号,由此内置的振荡器能够通过产生不同振动频率的方波来表达不同颜色光的光强,光强越大频率越高,频率信息从OUT引脚输出
这个模块所有的引脚是这样的:
VCC接正极,GND接负极,根据推荐工作条件,3.3V和5V都可以
STM32连着3.3V,STLink上有5V接头,VCC直连面包板正极或接5V都行
如图所示模块左右两边各有一个VCC和GND,我个人两边都接,也看到有人只接一边
都能成功运行
OUT引脚输出的频率与内置振荡器方波频率之间的比例可以通过S0和S1引脚的高低电平来调整,调整方式如下图所示
切换不同滤光片工作可以通过S2和S3引脚的高低电平来调整,调整方式如下图所示
它本尊长这样,说明书里写的是它能够测定不会自己发光的物体,这是因为他自带白光LED,会给出固定光源,我们在此处默认使用TCS3200测定颜色的物体都是无法自己发光的
STM32F103C8T6
非常常用的微处理器。
IC获取频率
IC(input capture)输入捕获
当通道输入引脚出现指定电平跳变时,当前CNT的值将被锁存到CCR中,可用于测量PWM波形的频率、占空比、脉冲间隔、电平持续时间等参数,每个高级定时器和通用定时器都拥有4个输入捕获通道
可配置为PWMI模式,同时测量频率和占空比,可配合主从触发模式,实现硬件全自动测量
在网上找的相关帖子很多都是用的中断,我跟着江协学完IC之后瞬间感觉可以用在这里,所以就来试试
上图是江协的ppt,u1s1江协的ppt做得真的好
代码
IC.c
#include "stm32f10x.h" // Device header
void IC_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//中断用了TIM2,IC使用TIM3吧
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//调用时钟
GPIO_InitTypeDef GPIO_InitStructure;//配置结构体
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);//GPIO初始化
//先初始化TIM【定时中断中有,直接复制,不用clearflag以及NVIC】
TIM_InternalClockConfig(TIM3);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//控制抖动滤波的,一分频
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1;//ARR这里防止计数溢出给一个最大值,满量程计数
TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;//PSC
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//高级计数器才有的,这里直接给0</