#include "gray_nomcu.h"
#include "usart.h"
#include "Adc.h"
No_MCU_Sensor gray;//gary是在头文件中No_MCU_Sensor结构体 后面定义的全局变量 extern No_MCU_Sensor gray;
unsigned short Anolog[8] = {0};
unsigned short white[8] = {2550, 3200, 2600, 2200, 3200, 3200, 3300, 1500};
unsigned short black[8] = {500, 800, 300, 300, 100, 600, 850, 100};
unsigned short Normal[8];
/* 函数功能:采集8个通道的模拟值并进行均值滤波
参数说明:result - 存储8个通道处理结果的数组 */
void Get_Analog_value(unsigned short *result) {
unsigned char i, j;
unsigned int Anolag = 0;
// 遍历8个传感器通道(3位地址线组合)
for (i = 0; i < 8; i++) {
// 通过地址线组合切换传感器通道(注意取反逻辑)
Switch_Address_0(!(i & 0x01)); // 地址线0,对应bit0
Switch_Address_1(!(i & 0x02)); // 地址线1,对应bit1
Switch_Address_2(!(i & 0x04)); // 地址线2,对应bit2
// 每个通道采集8次ADC值进行均值滤波
for (j = 0; j < 8; j++) {
Anolag += Get_adc_of_user(); // 累加ADC采样值
}
if (!Direction)
result[i] = Anolag / 8; // 计算平均值
else
result[7 - i] = Anolag / 8; // 计算平均值
Anolag = 0; // 重置累加器
}
}
/* 函数功能:将模拟值转换为数字信号(二值化处理)
参数说明:
adc_value - 原始ADC值数组
Gray_white - 白色阈值数组
Gray_black - 黑色阈值数组
Digital - 输出的数字信号(按位表示) */
void convertAnalogToDigital(unsigned short *adc_value,
unsigned short *Gray_white,
unsigned short *Gray_black,
unsigned char *Digital) {
for (int i = 0; i < 8; i++) {
if (adc_value[i] > Gray_white[i]) {
*Digital |= (1 << i); // 超过白阈值置1(白色)
} else if (adc_value[i] < Gray_black[i]) {
*Digital &= ~(1 << i); // 低于黑阈值置0(黑色)
}
// 中间灰度值保持原有状态
}
}
/* 函数功能:归一化ADC值到指定范围
参数说明:
adc_value - 原始ADC值数组
Normal_factor - 归一化系数数组
Calibrated_black - 校准黑值数组
result - 存储归一化结果的数组
bits - ADC最大量程值(如255/1024等) */
void normalizeAnalogValues(unsigned short *adc_value, double *Normal_factor,
unsigned short *Calibrated_black,
unsigned short *result, double bits) {
for (int i = 0; i < 8; i++) {
unsigned short n;
// 计算归一化值(减去黑电平后缩放)
if (adc_value[i] < Calibrated_black[i])
n = 0; // 低于黑电平归零
else
n = (adc_value[i] - Calibrated_black[i]) * Normal_factor[i];
// 限幅处理
if (n > bits) {
n = bits;
}
result[i] = n;
}
}
/* 函数功能:传感器结构体初始化(首次初始化)
参数说明:sensor - 传感器结构体指针 */
void No_MCU_Ganv_Sensor_Init_Frist(No_MCU_Sensor *sensor) {
// 清零所有校准数据和状态
memset(sensor->Calibrated_black, 0, 16);
memset(sensor->Calibrated_white, 0, 16);
memset(sensor->Normal_value, 0, 16);
memset(sensor->Analog_value, 0, 16);
// 初始化归一化系数
for (int i = 0; i < 8; i++) {
sensor->Normal_factor[i] = 0.0;
}
// 初始化状态变量
sensor->Digtal = 0;
sensor->Time_out = 0;
sensor->Tick = 0;
sensor->ok = 0; // 标记未完成校准
}
/* 函数功能:传感器完整初始化(带校准参数)
参数说明:
sensor - 传感器结构体指针
Calibrated_white - 校准白值数组
Calibrated_black - 校准黑值数组 */
void No_MCU_Ganv_Sensor_Init(No_MCU_Sensor *sensor,
unsigned short *Calibrated_white,
unsigned short *Calibrated_black) {
No_MCU_Ganv_Sensor_Init_Frist(sensor);
// 根据配置设置ADC量程
if (Sensor_ADCbits == _8Bits)
sensor->bits = 255.0;
else if (Sensor_ADCbits == _10Bits)
sensor->bits = 1024.0;
else if (Sensor_ADCbits == _12Bits)
sensor->bits = 4096.0;
else if (Sensor_ADCbits == _14Bits)
sensor->bits = 16384.0;
// 设置采样超时时间(基础版/青春版)
if (Sensor_Edition == Class)
sensor->Time_out = 1;
else
sensor->Time_out = 10;
double Normal_Diff[8];
unsigned short temp;
for (int i = 0; i < 8; i++) {
// 确保白值 > 黑值(必要时交换)
if (Calibrated_black[i] >= Calibrated_white[i]) {
temp = Calibrated_white[i];
Calibrated_white[i] = Calibrated_black[i];
Calibrated_black[i] = temp;
}
// 计算灰度阈值(1:2和2:1分界点)
sensor->Gray_white[i] =
(Calibrated_white[i] * 2 + Calibrated_black[i]) / 3;
sensor->Gray_black[i] =
(Calibrated_white[i] + Calibrated_black[i] * 2) / 3;
// 保存校准数据
sensor->Calibrated_black[i] = Calibrated_black[i];
sensor->Calibrated_white[i] = Calibrated_white[i];
// 处理无效校准数据(全黑/全白/相等情况)
if ((Calibrated_white[i] == 0 && Calibrated_black[i] == 0) ||
(Calibrated_white[i] == Calibrated_black[i])) {
sensor->Normal_factor[i] = 0.0; // 无效通道
continue;
}
// 计算归一化系数
Normal_Diff[i] =
(double)Calibrated_white[i] - (double)Calibrated_black[i];
sensor->Normal_factor[i] = sensor->bits / Normal_Diff[i];
}
sensor->ok = 1; // 标记初始化完成
}
/* 函数功能:传感器主任务(无定时器版本)*/
void No_Mcu_Ganv_Sensor_Task_Without_tick(No_MCU_Sensor *sensor) {
Get_Analog_value(sensor->Analog_value); // 采集数据
convertAnalogToDigital(sensor->Analog_value, sensor->Gray_white,
sensor->Gray_black, &sensor->Digtal); // 二值化处理
normalizeAnalogValues(sensor->Analog_value, sensor->Normal_factor,
sensor->Calibrated_black, sensor->Normal_value,
sensor->bits); // 归一化处理
}
/* 函数功能:传感器主任务(带定时器版本)*/
void No_Mcu_Ganv_Sensor_Task_With_tick(No_MCU_Sensor *sensor) {
if (sensor->Tick >= sensor->Time_out) // 检查是否到达采样周期
{
// 执行数据采集和处理
Get_Analog_value(sensor->Analog_value);
convertAnalogToDigital(sensor->Analog_value, sensor->Gray_white,
sensor->Gray_black, &sensor->Digtal);
normalizeAnalogValues(sensor->Analog_value, sensor->Normal_factor,
sensor->Calibrated_black, sensor->Normal_value,
sensor->bits);
sensor->Tick = 0; // 重置定时器
}
}
/* 函数功能:定时器tick递增 */
void Task_tick(No_MCU_Sensor *sensor) { sensor->Tick++; }
/* 函数功能:获取数字信号状态 */
unsigned char Get_Digtal_For_User(No_MCU_Sensor *sensor) {
return sensor->Digtal; // 返回8位数字状态(每位对应一个传感器)
}
/* 函数功能:获取归一化后的数据
返回值:1-成功 0-未初始化 */
unsigned char Get_Normalize_For_User(No_MCU_Sensor *sensor,
unsigned short *result) {
if (!sensor->ok)
return 0;
else {
memcpy(result, sensor->Normal_value, 16); // 拷贝归一化数据
return 1;
}
}
/* 函数功能:获取原始校准数据
返回值:1-成功 0-未初始化 */
unsigned char Get_Anolog_Value(No_MCU_Sensor *sensor, unsigned short *result) {
Get_Analog_value(sensor->Analog_value); // 重新采集数据
memcpy(result, sensor->Analog_value, 16);
if (!sensor->ok)
return 0;
else
return 1;
}
/************************************************功能测试函数**********************************/
// #include <include/project/project.h>
static unsigned char rx_buff[256] = {0};
void Gray_Show_Anolog(No_MCU_Sensor *sensor) {
// 获取传感器模拟量结果(有黑白值初始化后返回1 没有返回 0)
if (Get_Anolog_Value(sensor, Anolog)) {
sprintf((char *)rx_buff, "Anolog %d-%d-%d-%d-%d-%d-%d-%d\r\n",
Anolog[0], Anolog[1], Anolog[2], Anolog[3], Anolog[4],
Anolog[5], Anolog[6], Anolog[7]);
uart0_send_string((char *)rx_buff);
memset(rx_buff, 0, 256);
}
}
void Gray_Show_Digtal(No_MCU_Sensor *sensor) {
uint8_t Digtal = 0;
// 获取传感器数字量结果(只有当有黑白值传入进去了之后才会有这个值!!)
Digtal = Get_Digtal_For_User(sensor);
sprintf((char *)rx_buff, "Digtal %d-%d-%d-%d-%d-%d-%d-%d\r\n",
(Digtal >> 0) & 0x01, (Digtal >> 1) & 0x01, (Digtal >> 2) & 0x01,
(Digtal >> 3) & 0x01, (Digtal >> 4) & 0x01, (Digtal >> 5) & 0x01,
(Digtal >> 6) & 0x01, (Digtal >> 7) & 0x01);
uart0_send_string((char *)rx_buff);
memset(rx_buff, 0, 256);
}
void Gray_Show_Normalize(No_MCU_Sensor *sensor) {
// 获取传感器归一化结果(只有当有黑白值传入进去了之后才会有这个值!!有黑白值初始化后返回1
// 没有返回 0)
if (Get_Normalize_For_User(sensor, Normal)) {
sprintf((char *)rx_buff, "Normalize %d-%d-%d-%d-%d-%d-%d-%d\r\n",
Normal[0], Normal[1], Normal[2], Normal[3], Normal[4],
Normal[5], Normal[6], Normal[7]);
uart0_send_string((char *)rx_buff);
memset(rx_buff, 0, 256);
}
}
/****************************************巡线接口*************************************/
/**
* @brief 灰度传感器得到数字量误差等级,以中间为0
* @param data 灰度传感器得到的数字量
* @return 误差等级,范围约为[-56, 56],中间为8
*/
int GRAY_GetDigtalError(uint8_t data) {
int pos = -1;
for (int i = 0; i < 8; i++) {
if (!(data & (1 << i))) { // 扫到黑线
pos = i;
break;
}
}
if (pos == -1) return 0; // 没有扫到黑线
return (int)((pos - 3.5) * 16); // 以中间为0,左负右正,放大误差
}
/**
* @brief 获取灰度传感器的模拟量误差
*
* @return int 模拟量误差,具体变化量范围以黑白场校准值有关
*/
int GRAY_GetAnalogError() {
Get_Normalize_For_User(&gray, Normal); // 获取归一化数据
int result_1 = Normal[0] + Normal[1] + Normal[2] + Normal[3];
int result_2 = Normal[4] + Normal[5] + Normal[6] + Normal[7];
return result_1 - result_2;
}
/***********************************************自动校准的初始化
* ****************************************/
void Gray_Init(No_MCU_Sensor *sensor, unsigned short *Calibrated_white,
unsigned short *Calibrated_black, unsigned short *current_time) {
// 初始化传感器
No_MCU_Ganv_Sensor_Init(sensor, Calibrated_white, Calibrated_black);
}
这是我的gray_nomcu.c
#include "oled.h"
#include "stdlib.h"
#include "oledfont.h"
#include "stdio.h"
#include "delay.h"
uint8_t OLED_GRAM[128][8];
void OLED_Refresh_Gram(void)
{
uint8_t i,n;
for(i=0;i<8;i++)
{
OLED_WR_Byte (0xb0+i,OLED_CMD); //����ҳ��ַ��0~7��
OLED_WR_Byte (0x00,OLED_CMD); //������ʾλ�á��е͵�ַ
OLED_WR_Byte (0x10,OLED_CMD); //������ʾλ�á��иߵ�ַ
for(n=0;n<128;n++)OLED_WR_Byte(OLED_GRAM[n][i],OLED_DATA);
}
}
void OLED_WR_Byte(uint8_t dat,uint8_t cmd)
{
if(cmd)
OLED_DC_1;
else
OLED_DC_0;
for(uint8_t i=0;i<8;i++)
{
OLED_D0_0;
if(dat&0x80)OLED_D1_1;
else OLED_D1_0;
OLED_D0_1;
dat<<=1;
}
OLED_DC_1;
}
void OLED_Display_On(void)
{
OLED_WR_Byte(0X8D,OLED_CMD); //SET DCDC
OLED_WR_Byte(0X14,OLED_CMD); //DCDC ON
OLED_WR_Byte(0XAF,OLED_CMD); //DISPLAY ON
}
//�ر�OLED��ʾ
void OLED_Display_Off(void)
{
OLED_WR_Byte(0X8D,OLED_CMD); //SET DCDC
OLED_WR_Byte(0X10,OLED_CMD); //DCDC OFF
OLED_WR_Byte(0XAE,OLED_CMD); //DISPLAY OFF
}
void OLED_Clear(void)
{
uint8_t i,n;
for(i=0;i<8;i++)for(n=0;n<128;n++)OLED_GRAM[n][i]=0X00;
OLED_Refresh_Gram();
}
void OLED_DrawPoint(uint8_t x,uint8_t y,uint8_t t)
{
uint8_t pos,bx,temp=0;
if(x>127||y>63)return;
pos=7-y/8;
bx=y%8;
temp=1<<(7-bx);
if(t)OLED_GRAM[x][pos]|=temp;
else OLED_GRAM[x][pos]&=~temp;
}
void OLED_Fill(uint8_t x1,uint8_t y1,uint8_t x2,uint8_t y2,uint8_t dot)
{
uint8_t x,y;
for(x=x1;x<=x2;x++)
{
for(y=y1;y<=y2;y++)OLED_DrawPoint(x,y,dot);
}
OLED_Refresh_Gram();
}
void OLED_ShowChar(uint8_t x,uint8_t y,uint8_t chr,uint8_t size,uint8_t mode)
{
uint8_t temp,t,t1;
uint8_t y0=y;
uint8_t csize=(size/8+((size%8)?1:0))*(size/2);
chr=chr-' ';
for(t=0;t<csize;t++)
{
if(size==12)temp=asc2_1206[chr][t];
else if(size==16)temp=asc2_1608[chr][t];
else if(size==24)temp=asc2_2412[chr][t];
else return;
for(t1=0;t1<8;t1++)
{
if(temp&0x80)OLED_DrawPoint(x,y,mode);
else OLED_DrawPoint(x,y,!mode);
temp<<=1;
y++;
if((y-y0)==size)
{
y=y0;
x++;
break;
}
}
}
}
uint32_t mypow(uint8_t m,uint8_t n)
{
uint32_t result=1;
while(n--)result*=m;
return result;
}
void OLED_ShowNum(uint8_t x,uint8_t y,uint32_t num,uint8_t len,uint8_t size)
{
uint8_t t,temp;
uint8_t enshow=0;
for(t=0;t<len;t++)
{
temp=(num/mypow(10,len-t-1))%10;
if(enshow==0&&t<(len-1))
{
if(temp==0)
{
OLED_ShowChar(x+(size/2)*t,y,' ',size,1);
continue;
}else enshow=1;
}
OLED_ShowChar(x+(size/2)*t,y,temp+'0',size,1);
}
}
void OLED_ShowString(uint8_t x, uint8_t y, const char *p, uint8_t size)
{
while (*p != '\0') // 仍然可以用 '\0' 判断结束
{
if (x > (128 - (size/2))) { x = 0; y += size; }
if (y > (64 - size)) { y = x = 0; OLED_Clear(); }
OLED_ShowChar(x, y, *p, size, 1);
x += size/2;
p++;
}
}
//��ʾ���и���������
void OLED_ShowSNum(uint8_t x,uint8_t y,uint32_t num,uint8_t len,uint8_t size,uint8_t mode)
{
uint8_t t=0,temp,m=0;
if(size==8)m=2;
if(num<0)
{
OLED_ShowChar(x+(size/2+m)*t,y,'-',size,mode);
num = -num;
}
else
OLED_ShowChar(x+(size/2+m)*t,y,' ',size,mode);
for(t=1;t<len+1;t++)
{
temp=(num/mypow(10,len-t))%10;
if(temp==0)
{
OLED_ShowChar(x+(size/2+m)*t,y,'0',size,mode);
}
else
{
OLED_ShowChar(x+(size/2+m)*t,y,temp+'0',size,mode);
}
}
}
//��ʼ��SSD1306
void OLED_Init(void)
{
OLED_RES_0;
delay_ms(200);
OLED_RES_1;
OLED_WR_Byte(0xAE,OLED_CMD); //�ر���ʾ
OLED_WR_Byte(0xD5,OLED_CMD); //����ʱ�ӷ�Ƶ����,��Ƶ��
OLED_WR_Byte(80,OLED_CMD); //[3:0],��Ƶ����;[7:4],��Ƶ��
OLED_WR_Byte(0xA8,OLED_CMD); //��������·��
OLED_WR_Byte(0X3F,OLED_CMD); //Ĭ��0X3F(1/64)
OLED_WR_Byte(0xD3,OLED_CMD); //������ʾƫ��
OLED_WR_Byte(0X00,OLED_CMD); //Ĭ��Ϊ0
OLED_WR_Byte(0x40,OLED_CMD); //������ʾ��ʼ�� [5:0],����.
OLED_WR_Byte(0x8D,OLED_CMD); //��ɱ�����
OLED_WR_Byte(0x14,OLED_CMD); //bit2������/�ر�
OLED_WR_Byte(0x20,OLED_CMD); //�����ڴ��ַģʽ
OLED_WR_Byte(0x02,OLED_CMD); //[1:0],00���е�ַģʽ;01���е�ַģʽ;10,ҳ��ַģʽ;Ĭ��10;
OLED_WR_Byte(0xA1,OLED_CMD); //���ض�������,bit0:0,0->0;1,0->127;
OLED_WR_Byte(0xC0,OLED_CMD); //����COMɨ�跽��;bit3:0,��ͨģʽ;1,�ض���ģʽ COM[N-1]->COM0;N:����·��
OLED_WR_Byte(0xDA,OLED_CMD); //����COMӲ����������
OLED_WR_Byte(0x12,OLED_CMD); //[5:4]����
OLED_WR_Byte(0x81,OLED_CMD); //�Աȶ�����
OLED_WR_Byte(0xEF,OLED_CMD); //1~255;Ĭ��0X7F (��������,Խ��Խ��)
OLED_WR_Byte(0xD9,OLED_CMD); //����Ԥ�������
OLED_WR_Byte(0xf1,OLED_CMD); //[3:0],PHASE 1;[7:4],PHASE 2;
OLED_WR_Byte(0xDB,OLED_CMD); //����VCOMH ��ѹ����
OLED_WR_Byte(0x30,OLED_CMD); //[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;
OLED_WR_Byte(0xA4,OLED_CMD); //ȫ����ʾ����;bit0:1,����;0,�ر�;(����/����)
OLED_WR_Byte(0xA6,OLED_CMD); //������ʾ��ʽ;bit0:1,������ʾ;0,������ʾ
OLED_Clear();
OLED_WR_Byte(0xAF,OLED_CMD); //������ʾ
}
// void OLED_ShowDecimals(uint16_t x,uint16_t y,const uint8_t *p,uint8_t size,int get)
// {
// uint8_t test[10];
// while((*p<='~')&&(*p>=' '))
// {
// if(x>(128-(size/2))){x=0;y+=size;}
// if(y>(64-size)){y=x=0;OLED_Clear();}
// OLED_ShowChar(x,y,*p,size,1);
// x+=size/2;
// p++;
// }
// sprintf((char*)test,"%6i",get);
// printf("test is %sC\n",test);
// printf("\r\n");
// OLED_ShowString(x+2,y,test,size);
// }
void OLED_ShowDecimals(uint16_t x, uint16_t y, const char *p, uint8_t size, int get)
{
char test[12]; // 使用 char 类型缓冲区
// 显示前缀字符串
while (*p != '\0') // 使用空字符终止判断
{
if (x > (128 - (size/2))) {
x = 0;
y += size;
}
if (y > (64 - size)) {
y = x = 0;
OLED_Clear();
}
OLED_ShowChar(x, y, *p, size, 1);
x += size/2;
p++;
}
// 格式化数值并显示
snprintf(test, sizeof(test), "%6d", get); // 使用安全的 snprintf
printf("test is %sC\n", test);
printf("\r\n");
OLED_ShowString(x+2, y, test, size); // 直接传递 char 数组
}
//x,y:�������
//num :�ֿ��еڼ�������
//size:�����С
//mode��ģʽ0,������ʾ;1,������ʾ
void OLED_ShowCHinese(uint8_t x, uint8_t y, uint8_t num, uint8_t size,uint8_t mode)
{
uint8_t temp,t,t1;
uint8_t y0=y;
//uint8_t size = 16;
uint8_t csize=(size/8 + ((size%8)?1:0)) * size; //�õ�����һ���ַ���Ӧ������ռ���ֽ���
for(t=0;t<csize;t++)
{
// ��ֻ������16��12������ û��������������
if(size==12) temp = china_1212[num][t]; //����1212����
else if(size==16) temp = china_1616[num][t]; //����1616����
else return; //û�е��ֿ�
for(t1=0;t1<8;t1++)
{if(temp&0x80)OLED_DrawPoint(x,y,mode);
else OLED_DrawPoint(x,y,!mode);
temp<<=1;
y++;
if((y-y0)==size)
{y=y0;
x++;
break;
}
}
}
}
这是我的oled.c
#include "delay.h"
#include "gray_nomcu.h"
volatile unsigned int delay_times=0;
void Delay_us(uint32_t xus)
{
SysTick->LOAD = 72 * xus; //设置定时器重装值
SysTick->VAL = 0x00; //清空当前计数值
SysTick->CTRL = 0x00000005; //设置时钟源为HCLK,启动定时器
while(!(SysTick->CTRL & 0x00010000)); //等待计数到0
SysTick->CTRL = 0x00000004; //关闭定时器
}
void delay_ms(unsigned int ms)
{
delay_times=ms;
while(delay_times !=0);
}
void SysTick_Init(void)
{
DL_SYSTICK_config(CPUCLK_FREQ/1000);
NVIC_SetPriority(SysTick_IRQn, 0);
}
void SysTick_Handler(void)
{
Task_tick(&gray);
if(delay_times!=0)
{
delay_times--;
}
}
volatile uint32_t timer_ticks = 0; // 定时器计数器,每次中断递增
NonBlockingDelay stop_timer; // 定义一个非阻塞延时
/**
* @brief 初始化非阻塞延时结构体
* @param delay 非阻塞延时结构体指针
* @retval 无
*/
void Delay_Init(NonBlockingDelay *delay)
{
delay->start_time = 0;
delay->delay = 0;
delay->active = 0;
}
/**
* @brief 启动非阻塞延时
* @param delay 非阻塞延时结构体指针
* @param current_time 当前时间(通常为定时器计数值)
* @param delay_time 延时时间
* @retval 无
*/
void Delay_Start(NonBlockingDelay *delay, uint32_t current_time, uint32_t delay_time)
{
delay->start_time = current_time; // 记录当前时间
delay->delay = delay_time; // 设置延时时间
delay->active = 1; // 标记延时开始
}
/**
* @brief 检查非阻塞延时是否完成
* @param delay 非阻塞延时结构体指针
* @param current_time 当前时间(通常为定时器计数值)
* @retval 1 表示延时完成,0 表示延时未完成
*/
uint8_t Delay_Is_Completed(NonBlockingDelay *delay, uint32_t current_time)
{
if (delay->active && (current_time - delay->start_time >= delay->delay))
{
delay->active = 0; // 延时完成,清除标志位
return 1; // 返回延时完成
}
return 0; // 延时未完成
}
这是我的delay.c
#ifndef NO_MCU_GANV_GRAYSCALE_SENSOR_CONFIG_H_
#define NO_MCU_GANV_GRAYSCALE_SENSOR_CONFIG_H_
// #include <include/bsp/bsp.h>
#include <stdio.h>
#include <string.h>
#include "ti_msp_dl_config.h"
/**************************** 传感器版本配置 ****************************/
#define Class 0 // 经典版传感器
#define Younth 1 // 青春版传感器
/**************************** ADC分辨率配置 ****************************/
#define _14Bits 0 // 14位ADC模式
#define _12Bits 1 // 12位ADC模式
#define _10Bits 2 // 10位ADC模式
#define _8Bits 3 // 8位ADC模式
/**************************** 用户可配置区域 ***************************/
// 传感器版本选择(二选一)
#define Sensor_Edition Class // 使用基础版传感器
// #define Sensor_Edition Younth // 使用青春版传感器
/************************* 根据单片机自行选择 **************************/
// 输出结果方向,与预期方向不同选1
#define Direction 1
// ADC分辨率选择(四选一)
// #define Sensor_ADCbits _14Bits
#define Sensor_ADCbits _12Bits
// #define Sensor_ADCbits _10Bits
// #define Sensor_ADCbits _8Bits
// 定时器功能开关(需要时取消注释)
#define Use_Timer 1
/*************************** 硬件抽象层配置 ****************************/
// GPIO地址切换宏定义
#define Switch_Address_0(i) \
((i) ? (DL_GPIO_setPins(Gray_Address_PORT, Gray_Address_PIN_0_PIN)) \
: (DL_GPIO_clearPins(Gray_Address_PORT, \
Gray_Address_PIN_0_PIN))) // 地址位0控制
#define Switch_Address_1(i) \
((i) ? (DL_GPIO_setPins(Gray_Address_PORT, Gray_Address_PIN_1_PIN)) \
: (DL_GPIO_clearPins(Gray_Address_PORT, \
Gray_Address_PIN_1_PIN))) // 地址位1控制
#define Switch_Address_2(i) \
((i) ? (DL_GPIO_setPins(Gray_Address_PORT, Gray_Address_PIN_2_PIN)) \
: (DL_GPIO_clearPins(Gray_Address_PORT, \
Gray_Address_PIN_2_PIN))) // 地址位2控制
// ADC值获取接口宏定义 需要自己根据单片机完成对应位数的ADC采样函数
#define Get_adc_of_user() adc_getValue() // 用户自定义ADC读取函数
/**********************************************************************/
/*************************** 传感器数据结构 ***************************/
typedef struct {
unsigned short Analog_value[8]; // 原始模拟量值
int Error; // 巡线误差值
unsigned short Normal_value[8]; // 归一化后的值
unsigned short Calibrated_white[8]; // 白校准基准值
unsigned short Calibrated_black[8]; // 黑校准基准值
unsigned short Gray_white[8]; // 白平衡灰度值
unsigned short Gray_black[8]; // 黑平衡灰度值
double Normal_factor[8]; // 归一化系数
double bits; // ADC分辨率对应位数
unsigned char Digtal; // 数字输出状态
unsigned char Time_out; // 超时标志
unsigned char Tick; // 时基计数器
unsigned char ok; // 传感器就绪标志
} No_MCU_Sensor;
#ifdef __cplusplus
extern "C" {
#endif
extern No_MCU_Sensor gray;
extern unsigned short Anolog[8];
extern unsigned short white[8];
extern unsigned short black[8];
extern unsigned short Normal[8];
/*************************** 函数声明区域 *****************************/
// 初始化函数
void No_MCU_Ganv_Sensor_Init_Frist(No_MCU_Sensor* sensor); // 首次初始化
void No_MCU_Ganv_Sensor_Init(
No_MCU_Sensor* sensor, unsigned short* Calibrated_white,
unsigned short* Calibrated_black); // 带校准参数的初始化
#ifndef Use_Timer
// 任务处理函数
void No_Mcu_Ganv_Sensor_Task_Without_tick(No_MCU_Sensor* sensor); // 无时基版本
// 区别:后者使用定时器提供,需要一个1ms基准的定时器调用Task_tick(&sensor)函数,再将函数No_Mcu_Ganv_Sensor_Task_With_tick(&sensor)放入while1
// 前者只需要在while(1)里,delay 1ms,或者定时器1ms调用
// 前者优点:简单,方便,后者优点:能释放CPU,不需要通过delay完成这个任务,避免阻塞其他任务,同时避免了中断里处理事件,常驻任务优先级降低
#else
void No_Mcu_Ganv_Sensor_Task_With_tick(No_MCU_Sensor* sensor); // 有时基版本
void Task_tick(No_MCU_Sensor* sensor); // 时基更新函数
#endif
// 用户接口函数
unsigned char Get_Digtal_For_User(No_MCU_Sensor* sensor); // 获取数字量
unsigned char Get_Normalize_For_User(No_MCU_Sensor* sensor,
unsigned short* result); // 获取归一化值
unsigned char Get_Anolog_Value(No_MCU_Sensor* sensor,
unsigned short* result); // 获取模拟值
// 测试函数
void Gray_Show_Anolog(No_MCU_Sensor* sensor);
void Gray_Show_Digtal(No_MCU_Sensor* sensor);
void Gray_Show_Normalize(No_MCU_Sensor* sensor);
// 巡线支持
int GRAY_GetAnalog(uint8_t data);
int GRAY_GetAnalogError();
#ifdef __cplusplus
}
#endif
#endif /* NO_MCU_GANV_GRAYSCALE_SENSOR_CONFIG_H_ */
这是gray_nomcu.h
所有函数均已经定义 我要测灰度传感器返回的值显示在oled上
最新发布