STM32F103C8T6点灯/流水灯(指定IO,正向反向)

        参加2023年电赛后,到现在上班一年多,长达两年时间内,几乎没有再碰过单片机,由于现在工作中需要接触到一些代码,先退回来复习下32单片机。

        本人在此做一件事情,傻瓜式代码,让代码足够简洁,足够规范,让你复制我的代码百分百能够使用。此账号仅作为分享本人复习过程中记录使用,如果无法使用,或者或者有优化的地方,欢迎留言,看到后第一时间给予回复。有空会将2023激光打靶代码开源出来。

        在使用本程序的时候,默认你看过江科大的32工程的视频。(没看过的先回去恶补下)

LED.C

#include "stm32f10x.h"  

/**
  * @brief  LED控制函数
  * @param  GPIOx
  *   @arg  	在stm32f103C8T6这款单片机中,外设GPIO只有A,B,C三个
  * @param  GPIO_PIN_x
  *   @arg  	GPIO只有16个,范围1-16
  * @param  Power
  *   @arg		1开启,0关闭
  * @retval 无
  */
void LED_Optino(GPIO_TypeDef* GPIOx,uint16_t GPIO_PIN_x, uint8_t Power)
{
	if(GPIOx == GPIOA)//判断输入的GPIO开启对应的时钟
	{
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//开启GPIOA的时钟
	}else if(GPIOx == GPIOB)
	{
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//开启GPIOB的时钟
	}else if(GPIOx == GPIOC)
	{
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//开启GPIOC的时钟
	}

	GPIO_InitTypeDef GPIO_InitStructure;//IO初始化结构体
	
	//IO结构体的初始化
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_PIN_x;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOx,&GPIO_InitStructure);
	
	//LED开关
	if(Power == 1){GPIO_WriteBit(GPIOx,GPIO_PIN_x,Bit_RESET);}
		else {GPIO_WriteBit(GPIOx,GPIO_PIN_x,Bit_SET);}
}

LED.h

#ifndef __LED_H
#define __LED_H

void LED_Optino(GPIO_TypeDef* GPIOx,uint16_t GPIO_PIN_x, uint8_t Power);

#endif

main.c

#include "stm32f10x.h"                  // Device header
#include "LED.h"

int main(void)
{

	while(1)
	{
		LED_Optino(GPIOC,GPIO_Pin_13,0);
	}
}

流水灯笨蛋方法,自己定义需要点亮的灯,优势是比较简单,缺点是下一次想更换端口的时候,都需要更改一次源码。这里可以用GPIO_Write一次控制16个GPIO引脚来实现流水灯的方式。只不过需要再重写一次代码有点麻烦这里就不写了。

void waterfall_light(void)
{
	LED_Optino(GPIOB, GPIO_Pin_12, 1);
	LED_Optino(GPIOB, GPIO_Pin_13, 0);
	LED_Optino(GPIOB, GPIO_Pin_14, 0);
	LED_Optino(GPIOB, GPIO_Pin_15, 0);
	Delay_ms(500);
	LED_Optino(GPIOB, GPIO_Pin_12, 0);
	LED_Optino(GPIOB, GPIO_Pin_13, 1);
	LED_Optino(GPIOB, GPIO_Pin_14, 0);
	LED_Optino(GPIOB, GPIO_Pin_15, 0);
	Delay_ms(500);
	LED_Optino(GPIOB, GPIO_Pin_12, 0);
	LED_Optino(GPIOB, GPIO_Pin_13, 0);
	LED_Optino(GPIOB, GPIO_Pin_14, 1);
	LED_Optino(GPIOB, GPIO_Pin_15, 0);
	Delay_ms(500);
	LED_Optino(GPIOB, GPIO_Pin_12, 0);
	LED_Optino(GPIOB, GPIO_Pin_13, 0);
	LED_Optino(GPIOB, GPIO_Pin_14, 0);
	LED_Optino(GPIOB, GPIO_Pin_15, 1);
	Delay_ms(500);
}

高级一点的办法,由于PIN脚是一个uint16_t的变量,查看GPIO_PIN_的引脚定义,可以看到,每一位表示一个PIn脚,在手册中也可以看到端口端口输出数据寄存器(GPIOx_ODR)的高16位置为保留状态,低16位用于控制对应GPIO引脚,在得到参数2的最高位和最低位,就可以指定IO口进行流水灯操作了。

#define GPIO_Pin_0                 ((uint16_t)0x0001)  /*!< Pin 0 selected */
#define GPIO_Pin_1                 ((uint16_t)0x0002)  /*!< Pin 1 selected */
#define GPIO_Pin_2                 ((uint16_t)0x0004)  /*!< Pin 2 selected */
#define GPIO_Pin_3                 ((uint16_t)0x0008)  /*!< Pin 3 selected */
#define GPIO_Pin_4                 ((uint16_t)0x0010)  /*!< Pin 4 selected */
#define GPIO_Pin_5                 ((uint16_t)0x0020)  /*!< Pin 5 selected */
#define GPIO_Pin_6                 ((uint16_t)0x0040)  /*!< Pin 6 selected */
#define GPIO_Pin_7                 ((uint16_t)0x0080)  /*!< Pin 7 selected */
#define GPIO_Pin_8                 ((uint16_t)0x0100)  /*!< Pin 8 selected */
#define GPIO_Pin_9                 ((uint16_t)0x0200)  /*!< Pin 9 selected */
#define GPIO_Pin_10                ((uint16_t)0x0400)  /*!< Pin 10 selected */
#define GPIO_Pin_11                ((uint16_t)0x0800)  /*!< Pin 11 selected */
#define GPIO_Pin_12                ((uint16_t)0x1000)  /*!< Pin 12 selected */
#define GPIO_Pin_13                ((uint16_t)0x2000)  /*!< Pin 13 selected */
#define GPIO_Pin_14                ((uint16_t)0x4000)  /*!< Pin 14 selected */
#define GPIO_Pin_15                ((uint16_t)0x8000)  /*!< Pin 15 selected */
#define GPIO_Pin_All               ((uint16_t)0xFFFF)  /*!< All pins selected */
/**
  * @brief 找到最高位
  * @param  data
  *     @arg 传入的PIN脚
  * @retval 
  */
int16_t find_end(uint16_t data)
{
	if( data == 0) return -1;//没有1的存在
	uint16_t pos = 15;
	while((data & (1 << pos)) == 0)
	{
		pos--;
	}
	return pos;
}
/**
  * @brief 找到最低位
  * @param  data
  *     @arg 传入的PIN脚
  * @retval 
  */
int16_t find_Start(uint16_t data)
{
	if( data == 0) return -1;//没有1的存在
	uint16_t pos = 0;
	while((data & (1 << pos)) == 0)
	{
		pos++;
	}
	return pos;
}

void waterfall_light_advanced(GPIO_TypeDef* GPIOx,uint16_t GPIO_PIN_x, uint8_t direct)
{
	uint16_t end, start;
	end = find_end(GPIO_PIN_x);
	start = find_Start(GPIO_PIN_x);
	if(direct)
	{
		for(uint16_t i = start; i <= end; i++) //从低到高
		{
			LED_Optino(GPIOx,1<= start; i--)//从高到低
		{
			LED_Optino(GPIOx,1<

main.c

#include "stm32f10x.h"                  // Device header
#include "LED.h"

int main(void)
{

	while(1)
	{
		waterfall_light_advanced(GPIOA,GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11,0);
        waterfall_light_advanced(GPIOA,GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11,1);
	}
}

在此呼吁朋友们注意代码的通用性,尽量将代码编写成不用修改源码,只用改变不同的参数,就可以实现不同的一个功能,这样不仅仅是对自己是一个很大的提升,也是为了在比赛,工作中更好的配置。

        本人只学过江科大的51,32代码基础比较薄弱,如有错误,请大佬指出,定第一时间修改。(代码全部经过本人测试可以使用,如果需要整个工程,请留下邮箱)

你可能感兴趣的:(stm32,嵌入式硬件,单片机)