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(不再闪烁)
}
}
}
}