NEWLAB之光照度传感综合实验(二)——硬件抽象层hal代码

hal_iic.c

/******************************************************************************
*
*
*
*
*
******************************************************************************/

#include "delay.h"
#include "hal_iic.h"

/*短暂延时 1us */
#define _NOP_()	delay_us(2)

/* IIC初始化子程序 */
void IIC_Init(void)
{
	IIC_SDA_OUT_Init;
	IIC_SCL_Init;

	IIC_SDA_OUT = 1 ;
	IIC_SCL = 1 ;
}        

/* 停止I2C总线 */
void IIC_Stop(void)
{
	IIC_SDA_OUT = 0;
	_NOP_();
	IIC_SCL = 1;
	_NOP_();
	_NOP_();
	IIC_SDA_OUT = 1;  //总线置于空闲状态
	_NOP_();
}

/* 启动I2C总线 */
void IIC_Start(void)
{
	IIC_SDA_OUT = 1;
	IIC_SCL = 1;
	_NOP_();
	_NOP_();
	IIC_SDA_OUT = 0;
	_NOP_();
	_NOP_();
	IIC_SCL = 0;
}

/*IIC写一个字节 返回应答信号 返回HAL_I2C_OK设备正常*/
uint8_t IIC_WriteByte(uint8_t date)
{
	uint8_t i;
	uint8_t ack;
	for(i=0;i<8;i++)
	{
		IIC_SCL = 0;
		if(date&0x80)
		IIC_SDA_OUT = 1;
		else
		IIC_SDA_OUT = 0;
		_NOP_(); 
		IIC_SCL = 1;
		_NOP_();
		date  <<= 1;
	}
	IIC_SCL = 0;
	IIC_SDA_IN_Init;//作为输入口,8位发送完后释放数据线,准备接收应答位
	_NOP_();
	_NOP_();
	_NOP_();
	IIC_SCL = 1;
	i=0;
	while((i < 200) && (IIC_SDA_IN == 1))
	{
		_NOP_();
		i++;
	}
	_NOP_();
	if(IIC_SDA_IN == 0)//从机设备应答 
	{
		ack = HAL_I2C_OK;     
	}
	else 
	{
		ack = HAL_I2C_FAIL;
	}
	IIC_SCL = 0;
	_NOP_();
	return(ack);     
}

/************************************************************************
*IIC读一个字节  主机应答信号Master_ack为1是应答 0时非应答
*#define MASTER_ACK										1
*#define MASTER_NO_ACK								0
************************************************************************/
uint8_t IIC_ReadByte(uint8_t Master_ack)
{
	uint8_t i,vaule=0;
	for(i = 0;i <8;i++)
	{
		vaule <<= 1;
		IIC_SCL = 1;
		_NOP_();
		if(IIC_SDA_IN)
		{
			vaule |=0x01;
		}
		IIC_SCL = 0;
		_NOP_();
	}
	IIC_SDA_OUT_Init;//作为输出口,输出应答信号
	if(Master_ack != MASTER_NO_ACK)
	{
		IIC_SDA_OUT = 0;	//主机应答信号
	}
	else
	{
		IIC_SDA_OUT = 1;	//no 主机应答信号
	}
	_NOP_();
	IIC_SCL = 1;
	_NOP_();
	IIC_SCL = 0;
	_NOP_();
	return vaule;
}

hal_timer2.c

/*
******************************************************************************
* @file    TIM/TimeBase/main.c 
* @author  产品中心.硬件部
* @version V1.0.0
* @date    2017.09.07
* @brief   通用定时器2
******************************************************************************
*/

//Includes
#include "stm32f103_config.h"
#include "hal_timer2.h"
#include "hal_buzzer.h"
#include "ledNixietube.h"


TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

NVIC_InitTypeDef NVIC_InitStructure;
TIM_OCInitTypeDef  TIM_OCInitStructure;
uint16_t capture = 0;
__IO uint16_t CCR1_Val = 6000;//1ms,1KHz
__IO uint16_t CCR2_Val = 600;//0.1ms,10KHz
__IO uint16_t CCR3_Val = 120;//0.02ms,50KHz
__IO uint16_t CCR4_Val = 60000;//10ms,100Hz

uint16_t timer_20us_counter = 0; //定时20us时基寄存器
uint8_t FLAG_TIMER_GO = 0;//定时20us启动标志,运行-0;暂停-0。	
uint8_t FLAG_WHOLE_20US = 0; //用于保证每次定时都是20us整的地方开始取值

/*******************************************************************
*函数:void TIM2_Init(void)
*功能:定时器2初始化
*输入:无
*输出:无
*特殊说明:无
*******************************************************************/
void TIM2_Init(void)
{
	uint16_t PrescalerValue = 0;
	   
	/* --------------------------- System Clocks Configuration ---------------------*/
	/* TIM2 clock enable */
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

	/* --------------------------NVIC Configuration -------------------------------*/
	/* Enable the TIM2 gloabal Interrupt */
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

	NVIC_Init(&NVIC_InitStructure);
  
  
	/* ------------------- TIM2 Configuration:Output Compare Timing Mode ---------*/

	/* 
	SystemCoreClock = SYSCLK_FREQ_72MHz;
	PrescalerValue = (uint16_t) (SystemCoreClock / 6000000) - 1=11;
	TIM2 counter clock at SystemCoreClock/(PrescalerValue+1)=72/(11+1) MHz = 6 MHz
	CC1 update rate = TIM2 counter clock / CCR1_Val = 1KHz
	CC2 update rate = TIM2 counter clock / CCR2_Val = 10KHz
	CC3 update rate = TIM2 counter clock / CCR3_Val = 0.25KHz
	CC4 update rate = TIM2 counter clock / CCR4_Val = 0.1KHz
	*/

	/* Compute the prescaler value */
	PrescalerValue = (uint16_t) (SystemCoreClock / 6000000) - 1;//12分频=6MHz

	/* Time base configuration */
	TIM_TimeBaseStructure.TIM_Period = 65535;//自动重装载寄存器的值设置为65535(0xFFFF)
	//当计数器的值超过该数值时,计数器将从0开始重新计数。
	TIM_TimeBaseStructure.TIM_Prescaler = 0;
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

	/* Prescaler configuration */
	TIM_PrescalerConfig(TIM2, PrescalerValue, TIM_PSCReloadMode_Immediate);
	//TIM2、预分频值为0、立即更新

	/* Output Compare Timing Mode configuration: Channel1 */
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;//输出比较定时模式。
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_Pulse = CCR1_Val;//CCR1的值为6000,6000/6000000=1ms
	//计数器的值会和输出比较寄存器的值比较。当计数器的数值等于比较寄存器中的值时,会触发定时器中断。
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//输出高电平。

	TIM_OC1Init(TIM2, &TIM_OCInitStructure);//Ch1定时周期为1ms

	TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Disable);//立即写入输出比较寄存器CCR1

	/* Output Compare Timing Mode configuration: Channel2 */
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_Pulse = CCR2_Val;//600, 600/6000000=0.1ms
//计数器的值会和输出比较寄存器的值比较。当计数器的数值等于比较寄存器中的值时,会触发定时器中断。
	TIM_OC2Init(TIM2, &TIM_OCInitStructure);

	TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Disable);

	/* Output Compare Timing Mode configuration: Channel3 */
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_Pulse = CCR3_Val;//120, 120/6000000=20us
//计数器的值会和输出比较寄存器的值比较。当计数器的数值等于比较寄存器中的值时,会触发定时器中断。
	TIM_OC3Init(TIM2, &TIM_OCInitStructure);

	TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Disable);

	/* Output Compare Timing Mode configuration: Channel4 */
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_Pulse = CCR4_Val;//60000, 60000/6000000=10ms

	TIM_OC4Init(TIM2, &TIM_OCInitStructure);

	TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Disable);

	/* TIM IT enable */
	TIM_ITConfig(TIM2, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4, ENABLE);

	/* TIM2 enable counter */
	TIM_Cmd(TIM2, ENABLE);

}

/**
  * @brief  This function handles TIM2 global interrupt request.
  * @param  None
  * @retval None
  */
void TIM2_IRQHandler(void)
{
	if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)//如果CH1发生中断
	{
		TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);//清中断标志位
		//1ms定时进程		
		/***********************串口1接收超时进程处理************************/
		if(F_USART1_RX_RECEIVING)//正在接收串口数据
		{
			USART1_RX_TIMEOUT_COUNT++;//串口超时计数
			if(USART1_RX_TIMEOUT_COUNT>3)//数据接收间隔超过3ms
			{//串口接收完成或结束
				F_USART1_RX_RECEIVING=0;
				USART1_RX_TIMEOUT_COUNT=0;
				F_USART1_RX_FINISH=1;
			}
		}
		/***********************扫描数码管进程处理************************/
		led_scan();//扫描LED,每运行一次,点亮1位数码管,相当于每1ms点亮1位数码管。

		capture = TIM_GetCapture1(TIM2);//获得TIM2_CCR1寄存器的内容。
		TIM_SetCompare1(TIM2, capture + CCR1_Val);
		//将TIM2_CCR1的内容在现有数值基础上再加上6000,即等待下次1ms定时中断。
	}
	else if (TIM_GetITStatus(TIM2, TIM_IT_CC2) != RESET)//如果是CH2中断
	{
		TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);

		//100us定时进程,0.1ms,10kHz
		/***********************蜂鸣器鸣叫进程处理************************/
		HalBuzzerBlinkProcess();//蜂鸣器鸣叫

		capture = TIM_GetCapture2(TIM2);
		TIM_SetCompare2(TIM2, capture + CCR2_Val);//递增数为600.
	}
	else if (TIM_GetITStatus(TIM2, TIM_IT_CC3) != RESET)
	{
		TIM_ClearITPendingBit(TIM2, TIM_IT_CC3);

		//0.02ms,50KHz

		capture = TIM_GetCapture3(TIM2);
		TIM_SetCompare3(TIM2, capture + CCR3_Val);
	}
	else
	{
		TIM_ClearITPendingBit(TIM2, TIM_IT_CC4);

		//10ms定时进程

		capture = TIM_GetCapture4(TIM2);
		TIM_SetCompare4(TIM2, capture + CCR4_Val);
	}
}


/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

hal_usart1.c


```c
/******************************************************************************
* @ File name --> usart.c
* @ Author    --> By@ Sam Chan
* @ Version   --> V1.0
* @ Date      --> 10 - 20 - 2012
* @ Brief     --> 系统串口设置相关的函数
*
* @ Copyright (C) 20**
* @ All rights reserved
******************************************************************************/

#include <stdio.h>
#include "hal_usart1.h"


/******************************************************************************
           加入以下代码,支持printf函数,而不需要选择use MicroLIB
******************************************************************************/
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 
{ 
	int handle; 

}; 
// FILE is typedef’ d in stdio.h.  
FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
_sys_exit(int x) 
{ 
	x = x; 
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{      
	while((USART1->SR & 0x40) == 0);	//循环发送,直到发送完毕   
	USART1->DR = (uint8_t)ch;	//发送数据  
	return ch;
}

/*************************************   end   *******************************/


/******************************************************************************
* Function Name --> 初始化IO 串口1
* Description   --> none
* Input         --> bound:波特率	
* Output        --> none
* Reaturn       --> none 
******************************************************************************/
void USART1_Init(uint32_t bound)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	
#ifdef EN_USART1_RX	//如果使能了接收中断
	
	USART1->CR1 |= 1 << 8;	//PE中断使能
	USART1->CR1 |= 1 << 5;	//接收缓冲区非空中断使能
	
	MY_NVIC_Init(3, 3, USART1_IRQn, NVIC_PriorityGroup_2);	//中断分组2,最低优先级
	
#endif
	 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);	//使能USART1,GPIOA时钟
		
	USART_DeInit(USART1);  //复位串口1
	
	//USART1_TX   PA.9
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
	GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA9
   
	//USART1_RX	  PA.10
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
	GPIO_Init(GPIOA, &GPIO_InitStructure);  //初始化PA10
  
	//USART 初始化设置
	USART_InitStructure.USART_BaudRate = bound;	//设置波特率,一般设置为9600;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;	//字长为8位数据格式
	USART_InitStructure.USART_StopBits = USART_StopBits_1;	//一个停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;	//无奇偶校验位
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;	//无硬件数据流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式
	
	USART_Init(USART1, &USART_InitStructure); //初始化串口
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断
	USART_Cmd(USART1, ENABLE);                    //使能串口 
}

/******************************************************************************
* Function Name --> 串口1发送一个字节数据
* Description   --> nonevoid USART1_SendData(uint16_t Data)
* Input         --> bound:波特率	
* Output        --> none
* Reaturn       --> none 
******************************************************************************/
void USART1_SendData(uint16_t Data)
{
	while((USART1->SR & 0x40) == 0);	//等待发送完毕
	USART_SendData(USART1, Data);
}

/******************************************************************************
* Function Name --> 串口1发送一串数据
* Description   --> none
* Input         --> *Data:字符串	
* Output        --> none
* Reaturn       --> none 
******************************************************************************/
void USART1_SendStr(uint8_t *Data)
{
	while(*Data!='\0')
	{
		USART1_SendData((uint16_t )(*Data));
		Data++;
	}
}

//=========================================================
 
#ifdef EN_USART1_RX   //如果使能了接收

//=========================================================

//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误 

uint8_t USART1_RX_BUF[USART1_REC_LEN];	//接收缓冲,最大USART1_REC_LEN个字节



uint16_t USART1_RX_COUNT=0;	//接收到的有效字节数目,最大USART1_REC_LEN字节
uint8_t F_USART1_RX_FINISH=0;//接收状态标记,1:usart1接收完成,0:usart1接收未完成
uint8_t F_USART1_RX_RECEIVING=0;//串口接收正在进行中标记,1:进行中,0:暂停或结束
uint8_t USART1_RX_TIMEOUT_COUNT=0;	//串口接收超时计数。串口超过3ms未接收到数据,视为超时。单位:ms

/******************************************************************************
* Function Name --> 串口1接收中断服务程序
* Description   --> none
* Input         --> none
* Output        --> none
* Reaturn       --> none 
******************************************************************************/
void USART1_IRQHandler(void)
{
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收到数据
	{
		F_USART1_RX_RECEIVING=1;//正在接收串口数据
		USART1_RX_TIMEOUT_COUNT=0;//超时计数清零
		USART1_RX_BUF[USART1_RX_COUNT] = USART_ReceiveData(USART1);	//读取接收到的数据
		USART1_RX_COUNT++;
		if(USART1_RX_COUNT>USART1_REC_LEN)//缓存区溢出
		{USART1_RX_COUNT = 0x0000;}	
		//end 接收未完成   		 
	}	//end 接收到数据
}

//=========================================================

#endif	//end使能接收

//=========================================================

hal_buzzer.c

/******************************************************************************
* @ File name --> led.c
* @ Author    --> By@ MALIWEI
* @ Version   --> V1.0
* @ Date      --> 
* @ Brief     --> 蜂鸣器控制相关函数
*
* @ Copyright (C) 20**
* @ All rights reserved
******************************************************************************/

#include "hal_buzzer.h"

//全局变量
BuzzerState_TypeDef Buzzer_State;

/******************************************************************************
* Function Name --> Buzzer接口初始化
* Description   --> none
* Input         --> none
* Output        --> none
* Reaturn       --> none 
******************************************************************************/
void Buzzer_Init(void)
{
	STM32_GPIOx_Init(Buzzer0_Init);
	BUZZER0 = 0;
}

/***************************************************************************************************
 * @fn      HalBuzzerBlink
 *
 * @brief   Blink the leds
 *
 * @param   leds       - bit mask value of leds to be blinked
 *          numBlinks  - number of blinks
 *          percent    - the percentage in each period where the led
 *                       will be on
 *          period     - length of each cycle in milliseconds
 *
 * @return  None
 ***************************************************************************************************/
#define BUZZER_MULTIPLE 10
void HalBuzzerBlink (uint8_t leds, uint8_t numBlinks, uint8_t percent, uint16_t period)
{
  uint8_t led;
	uint8_t pos;
	HalBuzzerOnOff (leds, HAL_BUZZER_MODE_ON);
  if (leds && percent && period)
  {
    if (percent < 100)
    {
      led = HAL_BUZZER_0; //0x01
      leds &= HAL_BUZZER_ALL;//0x01
			pos=0;
      while (leds)
      {
        if (leds & led)
        {
					Buzzer_State.numBlinksGlobal[pos]=numBlinks;//闪烁次数;1
					Buzzer_State.percentGlobal[pos]=(period*BUZZER_MULTIPLE*percent)/100;//500*10*50/100=2500一个周期中亮的时长
					Buzzer_State.periodGlobal[pos]=period*BUZZER_MULTIPLE;//一个周期时长 500*10=5000
					Buzzer_State.BuzzerTimeCount[pos]=0;
					leds ^= led;
        }
				pos++;
        led <<= 1;
      }
    }
    else
    {
      HalBuzzerOnOff (leds, HAL_BUZZER_MODE_ON);                    /* >= 100%, turn on */
    }
  }
  else
  {
    HalBuzzerOnOff (leds, HAL_BUZZER_MODE_OFF);                     /* No on time, turn off */
  }
}

/***************************************************************************************************
 * @fn      HalBuzzerOnOff
 *
 * @brief   Turns specified Buzzer ON or OFF
 *
 * @param   leds - Buzzer bit mask
 *          mode - BUZZER_ON,BUZZER_OFF,
 *
 * @return  none
 ***************************************************************************************************/
void HalBuzzerOnOff (uint8_t leds, uint8_t mode)
{
  if (leds & HAL_BUZZER_0)
  {
    if (mode == HAL_BUZZER_MODE_ON)
    {
      HAL_TURN_ON_BUZZER0;
    }
    else
    {
      HAL_TURN_OFF_BUZZER0;
    }
  }
}

void HalBuzzerBlinkProcess ( void )
{
	uint8_t i;
	for(i=0;i<HAL_BUZZER_DEFAULT_MAX_BUZZERS;i++)
	{
		if(Buzzer_State.numBlinksGlobal[i]>0)
		{
			if(Buzzer_State.BuzzerTimeCount[i]<Buzzer_State.periodGlobal[i])//0<5000
				//-重复5000次,由于本函数是在TIM2的OC2中断周期调用,因此,时长为5000*0.1ms=500ms
			{
				if(Buzzer_State.BuzzerTimeCount[i]++<Buzzer_State.percentGlobal[i])//BuzzerTimeCountd+1
					//percent为2500,说明响的时间为250ms
				{
					HAL_TOGGLE_BUZZER0;//PA8状态取反
				}
				else
				{
					HAL_TURN_OFF_BUZZER0;//PA8=0;
				}
			}
			else
			{
				Buzzer_State.BuzzerTimeCount[i]=0;//计时器清零
				Buzzer_State.numBlinksGlobal[i]--;//闪烁次数减1(不再闪烁)
			}
		}
	}
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值