首页 > 其他分享 >红外对射传感器计次(江科大stm32学习笔记)

红外对射传感器计次(江科大stm32学习笔记)

时间:2024-10-20 20:21:55浏览次数:9  
标签:计次 void uint8 param stm32 OLED 科大 GPIO Line

本篇文章主要完成红外对射传感器计次的案例,为江科大stm32学习后的笔记记录。

硬件方面

如图所示为本次使用的红外对射传感器,根据相关说明书可知:模块槽中无遮挡时,接收管导通,模块DO输出低电平,遮挡时, DO 输出高电平;且有输出状态指示灯,输出高电平灯灭,输出低电平灯亮。

如图所示,①连接stm32最小系统板的GND和3.3V,以及STLINK。②连接显示屏GND对PB6,VDD对PB7,SCK对PB8,SDA对PB9。③连接红外传感器模块,先连接3.3V和GND,再将DO口接P至B14口。

软件方面

此例主要完成显示屏模块,红外传感器模块的模块化编程。

OLED的.c文件如下:

#include "stm32f10x.h"
#include "OLED_Font.h"

/*引脚配置*/
#define OLED_W_SCL(x)		GPIO_WriteBit(GPIOB, GPIO_Pin_8, (BitAction)(x))  //SCL接PB8
#define OLED_W_SDA(x)		GPIO_WriteBit(GPIOB, GPIO_Pin_9, (BitAction)(x))  //SDA接PB9

/*引脚初始化*/
void OLED_I2C_Init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
 	GPIO_Init(GPIOB, &GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
 	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	OLED_W_SCL(1);
	OLED_W_SDA(1);
}

/**
  * @brief  I2C开始
  * @param  无
  * @retval 无
  */
void OLED_I2C_Start(void)
{
	OLED_W_SDA(1);
	OLED_W_SCL(1);
	OLED_W_SDA(0);
	OLED_W_SCL(0);
}

/**
  * @brief  I2C停止
  * @param  无
  * @retval 无
  */
void OLED_I2C_Stop(void)
{
	OLED_W_SDA(0);
	OLED_W_SCL(1);
	OLED_W_SDA(1);
}

/**
  * @brief  I2C发送一个字节
  * @param  Byte 要发送的一个字节
  * @retval 无
  */
void OLED_I2C_SendByte(uint8_t Byte)
{
	uint8_t i;
	for (i = 0; i < 8; i++)
	{
		OLED_W_SDA(!!(Byte & (0x80 >> i)));
		OLED_W_SCL(1);
		OLED_W_SCL(0);
	}
	OLED_W_SCL(1);	//额外的一个时钟,不处理应答信号
	OLED_W_SCL(0);
}

/**
  * @brief  OLED写命令
  * @param  Command 要写入的命令
  * @retval 无
  */
void OLED_WriteCommand(uint8_t Command)
{
	OLED_I2C_Start();
	OLED_I2C_SendByte(0x78);		//从机地址
	OLED_I2C_SendByte(0x00);		//写命令
	OLED_I2C_SendByte(Command); 
	OLED_I2C_Stop();
}

/**
  * @brief  OLED写数据
  * @param  Data 要写入的数据
  * @retval 无
  */
void OLED_WriteData(uint8_t Data)
{
	OLED_I2C_Start();
	OLED_I2C_SendByte(0x78);		//从机地址
	OLED_I2C_SendByte(0x40);		//写数据
	OLED_I2C_SendByte(Data);
	OLED_I2C_Stop();
}

/**
  * @brief  OLED设置光标位置
  * @param  Y 以左上角为原点,向下方向的坐标,范围:0~7
  * @param  X 以左上角为原点,向右方向的坐标,范围:0~127
  * @retval 无
  */
void OLED_SetCursor(uint8_t Y, uint8_t X)
{
	OLED_WriteCommand(0xB0 | Y);					//设置Y位置
	OLED_WriteCommand(0x10 | ((X & 0xF0) >> 4));	//设置X位置高4位
	OLED_WriteCommand(0x00 | (X & 0x0F));			//设置X位置低4位
}

/**
  * @brief  OLED清屏
  * @param  无
  * @retval 无
  */
void OLED_Clear(void)
{  
	uint8_t i, j;
	for (j = 0; j < 8; j++)
	{
		OLED_SetCursor(j, 0);
		for(i = 0; i < 128; i++)
		{
			OLED_WriteData(0x00);
		}
	}
}

/**
  * @brief  OLED显示一个字符
  * @param  Line 行位置,范围:1~4
  * @param  Column 列位置,范围:1~16
  * @param  Char 要显示的一个字符,范围:ASCII可见字符
  * @retval 无
  */
void OLED_ShowChar(uint8_t Line, uint8_t Column, char Char)
{      	
	uint8_t i;
	OLED_SetCursor((Line - 1) * 2, (Column - 1) * 8);		//设置光标位置在上半部分
	for (i = 0; i < 8; i++)
	{
		OLED_WriteData(OLED_F8x16[Char - ' '][i]);			//显示上半部分内容
	}
	OLED_SetCursor((Line - 1) * 2 + 1, (Column - 1) * 8);	//设置光标位置在下半部分
	for (i = 0; i < 8; i++)
	{
		OLED_WriteData(OLED_F8x16[Char - ' '][i + 8]);		//显示下半部分内容
	}
}

/**
  * @brief  OLED显示字符串
  * @param  Line 起始行位置,范围:1~4
  * @param  Column 起始列位置,范围:1~16
  * @param  String 要显示的字符串,范围:ASCII可见字符
  * @retval 无
  */
void OLED_ShowString(uint8_t Line, uint8_t Column, char *String)
{
	uint8_t i;
	for (i = 0; String[i] != '\0'; i++)
	{
		OLED_ShowChar(Line, Column + i, String[i]);
	}
}

/**
  * @brief  OLED次方函数
  * @retval 返回值等于X的Y次方
  */
uint32_t OLED_Pow(uint32_t X, uint32_t Y)
{
	uint32_t Result = 1;
	while (Y--)
	{
		Result *= X;
	}
	return Result;
}

/**
  * @brief  OLED显示数字(十进制,正数)
  * @param  Line 起始行位置,范围:1~4
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~4294967295
  * @param  Length 要显示数字的长度,范围:1~10
  * @retval 无
  */
void OLED_ShowNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{
	uint8_t i;
	for (i = 0; i < Length; i++)							
	{
		OLED_ShowChar(Line, Column + i, Number / OLED_Pow(10, Length - i - 1) % 10 + '0');
	}
}

/**
  * @brief  OLED显示数字(十进制,带符号数)
  * @param  Line 起始行位置,范围:1~4
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:-2147483648~2147483647
  * @param  Length 要显示数字的长度,范围:1~10
  * @retval 无
  */
void OLED_ShowSignedNum(uint8_t Line, uint8_t Column, int32_t Number, uint8_t Length)
{
	uint8_t i;
	uint32_t Number1;
	if (Number >= 0)
	{
		OLED_ShowChar(Line, Column, '+');
		Number1 = Number;
	}
	else
	{
		OLED_ShowChar(Line, Column, '-');
		Number1 = -Number;
	}
	for (i = 0; i < Length; i++)							
	{
		OLED_ShowChar(Line, Column + i + 1, Number1 / OLED_Pow(10, Length - i - 1) % 10 + '0');
	}
}

/**
  * @brief  OLED显示数字(十六进制,正数)
  * @param  Line 起始行位置,范围:1~4
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~0xFFFFFFFF
  * @param  Length 要显示数字的长度,范围:1~8
  * @retval 无
  */
void OLED_ShowHexNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{
	uint8_t i, SingleNumber;
	for (i = 0; i < Length; i++)							
	{
		SingleNumber = Number / OLED_Pow(16, Length - i - 1) % 16;
		if (SingleNumber < 10)
		{
			OLED_ShowChar(Line, Column + i, SingleNumber + '0');
		}
		else
		{
			OLED_ShowChar(Line, Column + i, SingleNumber - 10 + 'A');
		}
	}
}

/**
  * @brief  OLED显示数字(二进制,正数)
  * @param  Line 起始行位置,范围:1~4
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~1111 1111 1111 1111
  * @param  Length 要显示数字的长度,范围:1~16
  * @retval 无
  */
void OLED_ShowBinNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{
	uint8_t i;
	for (i = 0; i < Length; i++)							
	{
		OLED_ShowChar(Line, Column + i, Number / OLED_Pow(2, Length - i - 1) % 2 + '0');
	}
}

/**
  * @brief  OLED初始化
  * @param  无
  * @retval 无
  */
void OLED_Init(void)
{
	uint32_t i, j;
	
	for (i = 0; i < 1000; i++)			//上电延时
	{
		for (j = 0; j < 1000; j++);
	}
	
	OLED_I2C_Init();			//端口初始化
	
	OLED_WriteCommand(0xAE);	//关闭显示
	
	OLED_WriteCommand(0xD5);	//设置显示时钟分频比/振荡器频率
	OLED_WriteCommand(0x80);
	
	OLED_WriteCommand(0xA8);	//设置多路复用率
	OLED_WriteCommand(0x3F);
	
	OLED_WriteCommand(0xD3);	//设置显示偏移
	OLED_WriteCommand(0x00);
	
	OLED_WriteCommand(0x40);	//设置显示开始行
	
	OLED_WriteCommand(0xA1);	//设置左右方向,0xA1正常 0xA0左右反置
	
	OLED_WriteCommand(0xC8);	//设置上下方向,0xC8正常 0xC0上下反置

	OLED_WriteCommand(0xDA);	//设置COM引脚硬件配置
	OLED_WriteCommand(0x12);
	
	OLED_WriteCommand(0x81);	//设置对比度控制
	OLED_WriteCommand(0xCF);

	OLED_WriteCommand(0xD9);	//设置预充电周期
	OLED_WriteCommand(0xF1);

	OLED_WriteCommand(0xDB);	//设置VCOMH取消选择级别
	OLED_WriteCommand(0x30);

	OLED_WriteCommand(0xA4);	//设置整个显示打开/关闭

	OLED_WriteCommand(0xA6);	//设置正常/倒转显示

	OLED_WriteCommand(0x8D);	//设置充电泵
	OLED_WriteCommand(0x14);

	OLED_WriteCommand(0xAF);	//开启显示
		
	OLED_Clear();				//OLED清屏
}

OLED的.h文件如下:

#ifndef __OLED_H
#define __OLED_H

void OLED_Init(void);//OLED初始化
void OLED_Clear(void);//屏幕清屏
void OLED_ShowChar(uint8_t Line, uint8_t Column, char Char);//输出字符
void OLED_ShowString(uint8_t Line, uint8_t Column, char *String);//输出字符串
void OLED_ShowNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length);//OLED显示数字(十进制,正数)
void OLED_ShowSignedNum(uint8_t Line, uint8_t Column, int32_t Number, uint8_t Length);  //OLED显示数字(十进制,带符号数)
void OLED_ShowHexNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length);//OLED显示数字(十六进制,正数)
void OLED_ShowBinNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length);//显示二进制数

#endif

计数器函数.c函数如下:

#include "stm32f10x.h"                  // Device header

uint16_t CountSensor_Count;				//用于计数

void CountSensor_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);		//打开GPIO时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);		//打开AFIO时钟
	
	GPIO_InitTypeDef GPIO_InitSructure;							//初始化GPIO
	GPIO_InitSructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitSructure.GPIO_Pin = GPIO_Pin_14;
	GPIO_InitSructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitSructure);
	
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);
	
	EXTI_InitTypeDef EXTI_InitStructure;						//初始化AFIO
	EXTI_InitStructure.EXTI_Line = EXTI_Line14;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;			//中断模式
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;    	//下降沿触发
	EXTI_Init(&EXTI_InitStructure);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);				//抢占和响应优先级分组方式设置
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
}


void EXTI15_10_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line14) == SET)					//看一下中断标志位是不是置1了
	{
		CountSensor_Count++;
		EXTI_ClearITPendingBit(EXTI_Line14);						//清除中断标志位,不然会一直在中断里面。
	}
}

uint16_t CountSensor_Get(void)
{
	return CountSensor_Count;
}

主要流程思路为

①配置时钟RCC

②配置GPIO,采用输入模式(此处为上拉输入)

③配置AFIP,选择GPIO并连接EXTI

④配置EXTI,选择边沿触发方式

⑤配置NVIC,设定中断优先级

计数器.h函数如下

#ifndef _COUNTSENSOR_H
#define _COUNTSENSOR_H

void CountSensor_Init(void);
uint16_t CountSensor_Get(void);

#endif

主函数.c文件如下:

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "CountSensor.h"

int main(void)
{
	OLED_Init();
	CountSensor_Init();
	
	while(1)
	{
		OLED_ShowString(1, 1, "Counts:");
		OLED_ShowNum(1, 8, CountSensor_Get(), 5);
	}
}

总结

当有物体通过或遮挡红外光线时,计数器次数加一。实现红外对射传感器计次功能。

标签:计次,void,uint8,param,stm32,OLED,科大,GPIO,Line
From: https://blog.csdn.net/2403_87367556/article/details/143096970

相关文章

  • 光敏电阻控制蜂鸣器(江科大stm32学习笔记)
    首先,选择模块化编程,使代码结构更加的清晰,整洁,便于更改。此处需要对蜂鸣器部分,光敏电阻传感器部分进行模块化编程。电路原理图对蜂鸣器以及光敏电阻传感器的电路原理图进行介绍。如图所示为蜂鸣器的电路原理图:采用三级管进行驱动,当PNP的基级引脚接低电平时,蜂鸣器启动,高电平......
  • stm32入门教程--TIM编码器接口
    TIM编码器接口是一种重要的硬件接口,主要用于接收增量(正交)编码器的信号。以下是对TIM编码器接口的详细介绍:一、功能与作用TIM编码器接口可以接收由编码器旋转产生的正交信号脉冲。这些信号脉冲被用来自动控制一个计数器(CNT)的自增或自减,从而能够指示编码器的位置、旋转方向和......
  • STM32 WINUSB1.0详细适配教程
    废话不多说,先上一个配置好的工程,急于完成适配的可先取走。需要了解原理或者适配后有问题的可继续阅读!通过网盘分享的文件:stm32h750_winusb.rarhttps://pan.baidu.com/s/1ENncscWVfQLHsOEhbe0sXQ?pwd=dr24 提取码:dr24说明:这个工程是基于STM32CUBEIDE1.9.0版本开发,配置了F......
  • 华中科大:通过慢思考评估LLM代码质量
    ......
  • 【TFT彩屏移植】STM32F4移植1.8寸TFT彩屏简明教程
    目录一.移植说明二.移植1.例程    物理接口:    延时函数:     底层驱动文件:    GUI界面文件:    测试demo:2.移植至F4创建工程:        调试接口选择SW:        RCC中HSE选择外部晶振:        GPIO配......
  • stm32是世界上最简单的
    例一include"stm32f10x.h"include"generic.h"//1.打开时钟2.配置3.初始化例子:点gpioa的第一个灯voidpin_init(GPIO_TypeDef*GPIOx,,uint16_tGPIO_Pin,GPIOMode_TypeDefGPIO_Mode){//直接调用这个函数if(GPIOx=GPIOA)RCC_APB2PeriphClockCdm(RCC_APB2Perph_GPIO......
  • 二、STM32F103C8T6-定时器
    STM32F103C8T6定时器概述STM32F103C8T6作为一款广泛使用的微控制器,内置多个定时器,能够支持多种计时和控制功能,如精确延时、脉冲宽度调制(PWM)、捕获比较(Capture/Compare)、输入捕获和输出比较等。这些功能在电机控制、信号测量、周期性事件触发等应用中非常常用。STM32F103C8T......
  • 解决一下、在学习江协科技stm32f103开发板操作寄存器无法点亮小灯,但是可以正常熄灭遇
    目录 本人问题:目前搜集网上有关信息有两种解决方案: 本人问题:问题:学习江协科技用操作寄存器的方式进行点亮小灯,代码正确,但是点亮小灯无法点亮,需要重新拔下来下载器再插入电脑USB口才可以点亮。但是熄灭小灯可以正常实现。本人代码:点亮:#include"stm32f10x.h"......
  • STM32 ADC实例解析(1)-寄存器方式
    文章目录一、寄存器列表二、示例代码三、总结优点:缺点:在很长的一段时间里我在项目中都是使用寄存器方式一、寄存器列表__IOuint32_tSR;/!<ADC状态寄存器,地址偏移量:0x00/__IOuint32_tCR1;/!<ADC控制寄存器1,地址偏移量:0x04/__IOuint32_tCR2;/!<ADC控制寄存......
  • STM32 ADC实例解析(1)-HAL+DMA方式
    文章目录一、STM32ADC与DMA的结合使用初始化ADC:配置DMA:启动DMA传输:中断处理(可选):二、示例代码初始化GPIO设置中断设置三、应用优势高效性:减轻CPU负担:灵活性:易用性:随着开发项目的累计,将ADC与DMA结合使用,可以实现高效的数据采集和处理。一、STM32ADC与DMA的结合......