New
This commit is contained in:
22
User/app/inc/demo_i2c_eeprom.h
Normal file
22
User/app/inc/demo_i2c_eeprom.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
*
|
||||
* 模块名称 : EEPROM读写演示模块。
|
||||
* 文件名称 : demo_i2c_eeprom.h
|
||||
* 版 本 : V1.0
|
||||
* 说 明 : 头文件
|
||||
*
|
||||
* Copyright (C), 2013-2014, 安富莱电子 www.armfly.com
|
||||
*
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _EEDEMO_H
|
||||
#define _EEDEMO_H
|
||||
|
||||
/* 供外部调用的函数声明 */
|
||||
void DemoEEPROM(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
21
User/app/inc/main.h
Normal file
21
User/app/inc/main.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
*
|
||||
* 模块名称 : main模块
|
||||
* 文件名称 : main.h
|
||||
* 版 本 : V1.0
|
||||
*
|
||||
* Copyright (C), 2015-2016, 安富莱电子 www.armfly.com
|
||||
*
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _MAIN_H_
|
||||
#define _MAIN_H_
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
|
||||
|
||||
215
User/app/src/demo_i2c_eeprom.c
Normal file
215
User/app/src/demo_i2c_eeprom.c
Normal file
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
*
|
||||
* 模块名称 : EEPROM读写演示模块。
|
||||
* 文件名称 : eeDemo.c
|
||||
* 版 本 : V1.1
|
||||
* 说 明 : EERPOM (24xx)读写例程。安富莱STM32-F4开发板标配的EEPROM型号为 AT24C128 (16K字节,128Kbit)
|
||||
*
|
||||
* 修改记录 :
|
||||
* 版本号 日期 作者 说明
|
||||
* V1.0 2013-02-01 armfly 正式发布
|
||||
* V1.1 2013-06-20 armfly 更换读取串口命令的写法,不采用 getchar() 阻塞方式。
|
||||
*
|
||||
* Copyright (C), 2013-2014, 安富莱电子 www.armfly.com
|
||||
*
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#include "bsp.h"
|
||||
|
||||
/* 仅允许本文件内调用的函数声明 */
|
||||
static void ee_DispMenu(void);
|
||||
static void ee_ReadTest(void);
|
||||
static void ee_WriteTest(void);
|
||||
static void ee_Erase(void);
|
||||
|
||||
uint8_t buf[EE_SIZE]; /* 数据测试用缓冲区 16KB */
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: DemoEEPROM
|
||||
* 功能说明: 串行EEPROM读写例程
|
||||
* 形 参:无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void DemoEEPROM(void)
|
||||
{
|
||||
uint8_t cmd;
|
||||
|
||||
if (ee_CheckOk() == 0)
|
||||
{
|
||||
/* 没有检测到EEPROM */
|
||||
printf("没有检测到串行EEPROM!\r\n");
|
||||
|
||||
while (1); /* 停机 */
|
||||
}
|
||||
|
||||
printf("已经检测到串行EEPROM : \r\n");
|
||||
printf("型号: %s, 容量 = %d 字节, 页面大小 = %d\r\n", EE_MODEL_NAME, EE_SIZE, EE_PAGE_SIZE);
|
||||
|
||||
ee_DispMenu(); /* 打印命令提示 */
|
||||
while(1)
|
||||
{
|
||||
bsp_Idle(); /* 这个函数在bsp.c文件。用户可以修改这个函数实现CPU休眠和喂狗 */
|
||||
|
||||
//cmd = getchar(); /* 从串口读入一个字符 (阻塞方式) */
|
||||
if (comGetChar(COM1, &cmd)) /* 从串口读入一个字符(非阻塞方式) */
|
||||
{
|
||||
switch (cmd)
|
||||
{
|
||||
case '1':
|
||||
printf("\r\n【1 - 读 EEPROM 测试】\r\n");
|
||||
ee_ReadTest(); /* 读EEPROM数据,并打印出来数据内容 */
|
||||
break;
|
||||
|
||||
case '2':
|
||||
printf("\r\n【2 - 写 EEPROM 测试】\r\n");
|
||||
ee_WriteTest(); /* 写EEPROM数据,并打印写入速度 */
|
||||
break;
|
||||
|
||||
case '3':
|
||||
printf("\r\n【3 - 擦除 EEPROM】\r\n");
|
||||
ee_Erase(); /* 擦差EEPROM数据,实际上就是写入全0xFF */
|
||||
break;
|
||||
|
||||
default:
|
||||
ee_DispMenu(); /* 无效命令,重新打印命令提示 */
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: ee_ReadTest
|
||||
* 功能说明: 读串行EEPROM全部数据,并打印出来
|
||||
* 形 参:无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
static void ee_ReadTest(void)
|
||||
{
|
||||
uint16_t i;
|
||||
int32_t iTime1, iTime2;
|
||||
|
||||
/* 读EEPROM, 起始地址 = 0, 数据长度为 256 */
|
||||
iTime1 = bsp_GetRunTime(); /* 记下开始时间 */
|
||||
if (ee_ReadBytes((uint8_t *)buf, 0, EE_SIZE) == 0)
|
||||
{
|
||||
printf("读eeprom出错!\r\n");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
iTime2 = bsp_GetRunTime(); /* 记下结束时间 */
|
||||
printf("读eeprom成功,数据如下:\r\n");
|
||||
}
|
||||
|
||||
/* 打印数据 */
|
||||
for (i = 0; i < EE_SIZE; i++)
|
||||
{
|
||||
printf(" %02X", buf[i]);
|
||||
|
||||
if ((i & 31) == 31)
|
||||
{
|
||||
printf("\r\n"); /* 每行显示16字节数据 */
|
||||
}
|
||||
else if ((i & 31) == 15)
|
||||
{
|
||||
printf(" - ");
|
||||
}
|
||||
}
|
||||
|
||||
/* 打印读速度 */
|
||||
printf("读耗时: %dms, 读速度: %dB/s\r\n", iTime2 - iTime1, (EE_SIZE * 1000) / (iTime2 - iTime1));
|
||||
}
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: ee_ReadTest
|
||||
* 功能说明: 写串行EEPROM全部数据
|
||||
* 形 参:无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
static void ee_WriteTest(void)
|
||||
{
|
||||
uint16_t i;
|
||||
int32_t iTime1, iTime2;
|
||||
|
||||
/* 填充测试缓冲区 */
|
||||
for (i = 0; i < EE_SIZE; i++)
|
||||
{
|
||||
buf[i] = i;
|
||||
}
|
||||
|
||||
/* 写EEPROM, 起始地址 = 0,数据长度为 256 */
|
||||
iTime1 = bsp_GetRunTime(); /* 记下开始时间 */
|
||||
if (ee_WriteBytes(buf, 0, EE_SIZE) == 0)
|
||||
{
|
||||
printf("写eeprom出错!\r\n");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
iTime2 = bsp_GetRunTime(); /* 记下结束时间 */
|
||||
printf("写eeprom成功!\r\n");
|
||||
}
|
||||
|
||||
|
||||
/* 打印读速度 */
|
||||
printf("写耗时: %dms, 写速度: %dB/s\r\n", iTime2 - iTime1, (EE_SIZE * 1000) / (iTime2 - iTime1));
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: ee_ReadTest
|
||||
* 功能说明: 读串行EEPROM全部数据,并打印出来
|
||||
* 形 参:无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
static void ee_Erase(void)
|
||||
{
|
||||
uint16_t i;
|
||||
|
||||
/* 填充缓冲区 */
|
||||
for (i = 0; i < EE_SIZE; i++)
|
||||
{
|
||||
buf[i] = 0xFF;
|
||||
}
|
||||
|
||||
/* 写EEPROM, 起始地址 = 0,数据长度为 256 */
|
||||
if (ee_WriteBytes(buf, 0, EE_SIZE) == 0)
|
||||
{
|
||||
printf("擦除eeprom出错!\r\n");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("擦除eeprom成功!\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: ee_DispMenu
|
||||
* 功能说明: 显示操作提示菜单
|
||||
* 形 参:无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
static void ee_DispMenu(void)
|
||||
{
|
||||
printf("\r\n------------------------------------------------\r\n");
|
||||
printf("请选择操作命令:\r\n");
|
||||
printf("1 - 读EEPROM (%d 字节)\r\n", EE_SIZE);
|
||||
printf("2 - 写EEPROM (%d 字节,0x00-0xFF)\r\n", EE_SIZE);
|
||||
printf("3 - 擦除EEPROM\r\n");
|
||||
printf("4 - 显示命令提示\r\n");
|
||||
}
|
||||
|
||||
/***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
|
||||
547
User/app/src/main-MF-MC-Design03.c
Normal file
547
User/app/src/main-MF-MC-Design03.c
Normal file
@@ -0,0 +1,547 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 模块名称:main
|
||||
// 文件名称:main
|
||||
// 版本名称:V1.0
|
||||
// 文件说明:旋转样品杆主文件
|
||||
// 日期时间:2018年8月16日21点38分
|
||||
// 文件作者:Jackie Chan
|
||||
// 修改记录:
|
||||
// 版本号 日期 作者 说明
|
||||
// V1.0 2018.08.16 J.C 正式发布
|
||||
//
|
||||
// 公司名称:多场低温科技有限公司
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#include "bsp.h" /* 底层硬件驱动 */
|
||||
uint8_t Flag_100ms = 0;
|
||||
extern DIGITIAL_TUBE_T g_tTube;
|
||||
extern MOTO_T g_tMoto;
|
||||
#define IS_ZERO_BUF_VALID() (g_RxBuf[1]=='z' && \
|
||||
g_RxBuf[2]==',' && g_RxBuf[4]==',' && \
|
||||
(g_RxBuf[3]=='1' || g_RxBuf[3]=='0'))
|
||||
#define IS_MF_VALID (g_RxBuf[1]=='M' && g_RxBuf[2]=='F')
|
||||
static void Delay_ms(uint16_t us)
|
||||
{
|
||||
uint16_t i;
|
||||
|
||||
/*
|
||||
CPU主频168MHz时,在内部Flash运行, MDK工程不优化。用台式示波器观测波形。
|
||||
循环次数为5时,SCL频率 = 1.78MHz (读耗时: 92ms, 读写正常,但是用示波器探头碰上就读写失败。时序接近临界)
|
||||
循环次数为10时,SCL频率 = 1.1MHz (读耗时: 138ms, 读速度: 118724B/s)
|
||||
循环次数为30时,SCL频率 = 440KHz, SCL高电平时间1.0us,SCL低电平时间1.2us
|
||||
|
||||
上拉电阻选择2.2K欧时,SCL上升沿时间约0.5us,如果选4.7K欧,则上升沿约1us
|
||||
|
||||
实际应用选择400KHz左右的速率即可
|
||||
*/
|
||||
for (i = 0; i < (300*us); i++);
|
||||
}
|
||||
void key1_long_task(void);
|
||||
void key1_task(void);
|
||||
void key2_task(void);
|
||||
void uart_msg_idle(void);
|
||||
// #include "bsp_adc.h"
|
||||
// #include "delay.h"
|
||||
|
||||
//初始化ADC
|
||||
//这里我们仅以规则通道为例
|
||||
//我们默认将开启通道0~3
|
||||
void Adc_Init(void)
|
||||
{
|
||||
ADC_InitTypeDef ADC_InitStructure;
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1, ENABLE ); //使能ADC1通道时钟
|
||||
|
||||
|
||||
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
|
||||
|
||||
//PA1 作为模拟通道输入引脚
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入引脚
|
||||
GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||||
|
||||
ADC_DeInit(ADC1); //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值
|
||||
|
||||
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作模式:ADC1和ADC2工作在独立模式
|
||||
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //模数转换工作在单通道模式
|
||||
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //模数转换工作在单次转换模式
|
||||
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动
|
||||
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐
|
||||
ADC_InitStructure.ADC_NbrOfChannel = 1; //顺序进行规则转换的ADC通道的数目
|
||||
ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器
|
||||
|
||||
|
||||
ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1
|
||||
|
||||
ADC_ResetCalibration(ADC1); //使能复位校准
|
||||
|
||||
while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束
|
||||
|
||||
ADC_StartCalibration(ADC1); //开启AD校准
|
||||
|
||||
while(ADC_GetCalibrationStatus(ADC1)); //等待校准结束
|
||||
|
||||
// ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能
|
||||
|
||||
}
|
||||
//获得ADC值
|
||||
//ch:通道值 0~3 ADC_Channel_1
|
||||
u16 Get_Adc(u8 ch)
|
||||
{
|
||||
//设置指定ADC的规则组通道,一个序列,采样时间
|
||||
ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 ); //ADC1,ADC通道,采样时间为239.5周期
|
||||
|
||||
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能
|
||||
|
||||
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束
|
||||
|
||||
return ADC_GetConversionValue(ADC1); //返回最近一次ADC1规则组的转换结果
|
||||
}
|
||||
|
||||
u16 Get_Adc_Average(u8 ch,u8 times)
|
||||
{
|
||||
u32 temp_val=0;
|
||||
u8 t;
|
||||
for(t=0;t<times;t++)
|
||||
{
|
||||
temp_val+=Get_Adc(ch);
|
||||
Delay_ms(5);
|
||||
}
|
||||
return temp_val/times;
|
||||
}
|
||||
|
||||
u16 get_key4_adc(void)
|
||||
{
|
||||
u16 key4_adc = 0;
|
||||
u16 ad_value;
|
||||
|
||||
ad_value = Get_Adc_Average(ADC_Channel_1,10);
|
||||
|
||||
// electric_quantity_percent = ((ad_value*3.3/4096.0)-1.846)*100/0.52;
|
||||
// key4_adc = (ad_value*3.3/4096.0);
|
||||
|
||||
key4_adc = ad_value;
|
||||
if(key4_adc > 2100)
|
||||
{
|
||||
key4_adc = 2;//前进
|
||||
}
|
||||
else if(key4_adc <= 1100)
|
||||
{
|
||||
key4_adc = 1;//后退
|
||||
}
|
||||
else if((key4_adc > 1100)&&(key4_adc <= 2100))
|
||||
{
|
||||
key4_adc = 0;//后退
|
||||
}
|
||||
return key4_adc;
|
||||
}
|
||||
u16 get_key5_adc(void)
|
||||
{
|
||||
u16 key5_adc = 0;
|
||||
u16 ad_value;
|
||||
|
||||
ad_value = Get_Adc_Average(ADC_Channel_2,10);
|
||||
|
||||
// electric_quantity_percent = ((ad_value*3.3/4096.0)-1.846)*100/0.52;
|
||||
key5_adc = (ad_value*3.3/4096.0);
|
||||
|
||||
if(key5_adc >= 2800)
|
||||
{
|
||||
key5_adc = 1;//前进
|
||||
}
|
||||
else if(key5_adc <= 600)
|
||||
{
|
||||
key5_adc = 2;//后退
|
||||
}
|
||||
else if((key5_adc > 600)&&(key5_adc < 2800))
|
||||
{
|
||||
key5_adc = 0;//后退
|
||||
}
|
||||
return key5_adc;
|
||||
}
|
||||
|
||||
void motor_dir(uint32_t freq, uint8_t _dir, int32_t _stpes)
|
||||
{
|
||||
// [r,1,1500,108288]
|
||||
// freq = get_run_freq();
|
||||
// pulse = get_pulse();
|
||||
if(g_tTube.state == WORK)
|
||||
{
|
||||
if(_dir == 1)
|
||||
{
|
||||
_dir = 1;
|
||||
g_tMoto.sv_pulse = g_tMoto.sv_pulse+100;
|
||||
}
|
||||
else if(_dir == 0)
|
||||
{
|
||||
_dir = 0;
|
||||
g_tMoto.sv_pulse = g_tMoto.sv_pulse-100;
|
||||
}
|
||||
|
||||
if(g_tMoto.pv_pulse<g_tMoto.sv_pulse)
|
||||
{
|
||||
if (g_tMoto.sv_pulse > 55600)
|
||||
{
|
||||
g_tMoto.sv_pulse = 55600;
|
||||
}
|
||||
else if(g_tMoto.sv_pulse <= 55600)
|
||||
{
|
||||
MOTO_Start(freq, 0, 100);
|
||||
}
|
||||
}
|
||||
else if(g_tMoto.pv_pulse>g_tMoto.sv_pulse)
|
||||
{
|
||||
if (g_tMoto.sv_pulse < -1600)
|
||||
{
|
||||
g_tMoto.sv_pulse = -1600;
|
||||
}
|
||||
else if(g_tMoto.sv_pulse >= -1600)
|
||||
{
|
||||
MOTO_Start(freq, 1, 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
int main(void)
|
||||
{
|
||||
uint8_t ucKeyCode;
|
||||
uint32_t freq = 1500;
|
||||
uint16_t motor_move1 = 0;
|
||||
uint16_t motor_move2 = 0;
|
||||
bsp_Init(); /* 硬件初始化 */
|
||||
Adc_Init(); //ADC初始化
|
||||
BEEP_Start(freq, 20, 1, 1);
|
||||
|
||||
//g_tTube.state = WORK;
|
||||
// MOTO_Stop();
|
||||
//g_tMoto.CurrentStep = 0;
|
||||
|
||||
/* 主程序大循环 */
|
||||
while (1)
|
||||
{
|
||||
bsp_Idle(); /* CPU空闲时执行的函数,在 bsp.c */
|
||||
uart_msg_idle();
|
||||
if(Flag_100ms == 1)
|
||||
{
|
||||
Flag_100ms = 0;
|
||||
motor_move1 = get_key4_adc();
|
||||
motor_move2 = get_key5_adc();
|
||||
if(motor_move1 == 1)//key4
|
||||
{
|
||||
motor_move1 = 0;
|
||||
//前进
|
||||
motor_dir(1500, 0, 3000);
|
||||
}
|
||||
else if(motor_move1 == 2)
|
||||
{
|
||||
motor_move1 = 0;
|
||||
//后退
|
||||
motor_dir(1500, 1, 3000);
|
||||
}
|
||||
}
|
||||
/* 处理按键事件 */
|
||||
ucKeyCode = bsp_GetKey();
|
||||
|
||||
if (ucKeyCode > 0)
|
||||
{
|
||||
/* 有键按下 */
|
||||
switch (ucKeyCode)//key6
|
||||
{
|
||||
case KEY_DOWN_K6: //key6 短按
|
||||
{
|
||||
BEEP_KeyTone(); // 按键提示音
|
||||
key1_long_task(); // 短按按键一仅用来切换数码管显示角度还是脉冲数
|
||||
break;
|
||||
}
|
||||
|
||||
case KEY_DOWN_K1: //Key1 短按
|
||||
{
|
||||
BEEP_KeyTone(); // 按键提示音
|
||||
bsp_ToogleDispMode(); // K1按键用来做零点搜索时候的限位
|
||||
break;
|
||||
}
|
||||
case KEY_DOWN_K2: //Key2 短按
|
||||
{
|
||||
BEEP_KeyTone(); // 按键提示音
|
||||
|
||||
key2_task(); // K2按键用来做零点搜索时候的限位
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case KEY_LONG_K1://
|
||||
{
|
||||
//BEEP_Start(freq, 5, 5, 3); // 长按K1发出三声嘀嘀声
|
||||
key1_long_task(); //
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void key1_long_task(void)
|
||||
{ // 转速:10度每秒
|
||||
if(IsKeyDown2())
|
||||
{
|
||||
BEEP_Start(1500, 5, 5, 3);
|
||||
// 如果已经在零点了,发出提醒,不转动,位置归零
|
||||
}
|
||||
if(g_tTube.state == IDLE)
|
||||
{
|
||||
g_tTube.state = SEARCH; // 上电后,长按K1进入搜索零点模式
|
||||
if(g_tTube.disp_mode == MODE_PULSE)
|
||||
{
|
||||
bsp_drv8880_config_dir(DIR_CW);
|
||||
MOTO_Start(1504, 1, 67680); // 67680个脉冲,无限位防护最大旋转1.25圈
|
||||
} // 转速:10度每秒
|
||||
else if(g_tTube.disp_mode == MODE_ANGLE)
|
||||
{
|
||||
bsp_drv8880_config_dir(DIR_CCW);
|
||||
MOTO_Start(1504,1, 67680); // 67680个脉冲,无限位防护最大旋转1.25圈
|
||||
}
|
||||
}
|
||||
else if(g_tTube.state == WORK && g_tMoto.CurrentStep != 0)
|
||||
{
|
||||
g_tTube.state = SEARCH; // 上电后,长按K1进入搜索零点模式
|
||||
if(g_tTube.disp_mode == MODE_PULSE)
|
||||
{
|
||||
bsp_drv8880_config_dir(DIR_CW);
|
||||
MOTO_Start(1504, 1, 67680); // 67680个脉冲,无限位防护最大旋转1.25圈
|
||||
} // 转速:10度每秒
|
||||
else if(g_tTube.disp_mode == MODE_ANGLE)
|
||||
{
|
||||
bsp_drv8880_config_dir(DIR_CCW);
|
||||
MOTO_Start(1504,1, 67680); // 67680个脉冲,无限位防护最大旋转1.25圈
|
||||
}
|
||||
}
|
||||
// 转速:10度每秒
|
||||
}
|
||||
|
||||
void key2_task(void)
|
||||
{
|
||||
DISABLE_INT();
|
||||
if(g_tTube.state == SEARCH)
|
||||
{
|
||||
g_tTube.state = WORK;
|
||||
MOTO_Stop();
|
||||
g_tMoto.CurrentStep = 0;
|
||||
}
|
||||
ENABLE_INT();
|
||||
}
|
||||
|
||||
uint32_t get_run_freq(void) // [r,1,1500,108288]
|
||||
{
|
||||
uint32_t i=0;
|
||||
i += (g_RxBuf[5]-'0')*1000;
|
||||
i += (g_RxBuf[6]-'0')*100;
|
||||
i += (g_RxBuf[7]-'0')*10;
|
||||
i += (g_RxBuf[8]-'0')*1;
|
||||
return i;
|
||||
}
|
||||
|
||||
uint32_t get_zero_freq(void) // [z,1,1500]
|
||||
{
|
||||
uint32_t i=0;
|
||||
i += (g_RxBuf[5]-'0')*1000;
|
||||
i += (g_RxBuf[6]-'0')*100;
|
||||
i += (g_RxBuf[7]-'0')*10;
|
||||
i += (g_RxBuf[8]-'0')*1;
|
||||
return i;
|
||||
}
|
||||
|
||||
uint32_t get_pulse(void)
|
||||
{
|
||||
uint32_t i=0;
|
||||
i += (g_RxBuf[10]-'0')*100000;
|
||||
i += (g_RxBuf[11]-'0')*10000;
|
||||
i += (g_RxBuf[12]-'0')*1000;
|
||||
i += (g_RxBuf[13]-'0')*100;
|
||||
i += (g_RxBuf[14]-'0')*10;
|
||||
i += (g_RxBuf[15]-'0')*1;
|
||||
return i;
|
||||
}
|
||||
|
||||
void search_zero(uint8_t dir,uint32_t freq)
|
||||
{
|
||||
if(g_tMoto.Running == 1) // 如果电机在运动中,先停止电机
|
||||
{
|
||||
MOTO_Stop();
|
||||
}
|
||||
|
||||
// 转速:10度每秒
|
||||
if(IsKeyDown2())
|
||||
{
|
||||
BEEP_Start(1500, 5, 5, 3);
|
||||
// 如果已经在零点了,发出提醒,不转动,位置归零
|
||||
}
|
||||
if(g_tTube.state == IDLE)
|
||||
{
|
||||
g_tTube.state = SEARCH; // 上电后,长按K1进入搜索零点模式
|
||||
if(g_tTube.disp_mode == MODE_PULSE)
|
||||
{
|
||||
bsp_drv8880_config_dir(DIR_CW);
|
||||
MOTO_Start(1504, 1, 67680); // 67680个脉冲,无限位防护最大旋转1.25圈
|
||||
} // 转速:10度每秒
|
||||
else if(g_tTube.disp_mode == MODE_ANGLE)
|
||||
{
|
||||
bsp_drv8880_config_dir(DIR_CCW);
|
||||
MOTO_Start(1504,1, 67680); // 67680个脉冲,无限位防护最大旋转1.25圈
|
||||
}
|
||||
}
|
||||
else if(g_tTube.state == WORK && g_tMoto.CurrentStep != 0)
|
||||
{
|
||||
g_tTube.state = SEARCH; // 上电后,长按K1进入搜索零点模式
|
||||
if(g_tTube.disp_mode == MODE_PULSE)
|
||||
{
|
||||
bsp_drv8880_config_dir(DIR_CW);
|
||||
MOTO_Start(1504, 1, 67680); // 67680个脉冲,无限位防护最大旋转1.25圈
|
||||
} // 转速:10度每秒
|
||||
else if(g_tTube.disp_mode == MODE_ANGLE)
|
||||
{
|
||||
bsp_drv8880_config_dir(DIR_CCW);
|
||||
MOTO_Start(1504,1, 67680); // 67680个脉冲,无限位防护最大旋转1.25圈
|
||||
}
|
||||
}
|
||||
// 转速:10度每秒
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void send_sv_2_uart(void)
|
||||
{
|
||||
if(g_tMoto.pv_pulse>=0)
|
||||
{
|
||||
printf("[w,1,%06d]",g_tMoto.pv_pulse);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[w,0,%06d]",-g_tMoto.pv_pulse);
|
||||
}
|
||||
}
|
||||
|
||||
void print_sys_info(void)
|
||||
{
|
||||
printf("\r\n");
|
||||
printf("----------------------------->\r\n");
|
||||
printf("-> 设备名称:旋转样品杆控制器\r\n");
|
||||
printf("-> software verson: V1.1\r\n");
|
||||
printf("-> compile time: %s\r\n",__TIME__);
|
||||
printf("-> compile date: %s\r\n",__DATE__);
|
||||
printf("-> [多场低温科技有限公司]\r\n");
|
||||
printf("------------------------------\r\n");
|
||||
printf("->可用命令:\r\n");
|
||||
printf("1. [s] // 停止电机转动\r\n");
|
||||
printf("2. [?] // 读取当前位置脉冲数量\r\n");
|
||||
printf("3. [MF] // 打印系统信息\r\n");
|
||||
printf("4. [z,1,1500] // 零点搜索命令,1为顺时针转动,0为逆时针转动,1500为脉冲频率\r\n");
|
||||
printf("5. [r,1,1500,108288] // 转动命令,1为顺时针转动,0为逆时针转动,1500为脉冲频率,108288为要转动的脉冲\r\n");
|
||||
printf("<-----------------------------\r\n");
|
||||
}
|
||||
|
||||
void uart_msg_idle(void)
|
||||
{
|
||||
uint8_t n=0;
|
||||
uint32_t freq=0;
|
||||
uint32_t pulse=0;
|
||||
uint8_t _dir=0;
|
||||
|
||||
if(g_ucRxRcvNewFlag)
|
||||
{
|
||||
g_ucRxRcvNewFlag = 0;
|
||||
|
||||
n = strlen((char*)g_RxBuf);
|
||||
if(n==3)
|
||||
{
|
||||
switch(g_RxBuf[1])
|
||||
{
|
||||
//case '?': printf("%d\r\n",g_tTube.pulse); break;
|
||||
//case '?': printf("[w,1,054050]"); break;
|
||||
case '?': send_sv_2_uart(); break;
|
||||
case 's': MOTO_Stop(); break;
|
||||
//case 'z': search_zero(1); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
else if(n==4)
|
||||
{
|
||||
if(IS_MF_VALID)
|
||||
{
|
||||
print_sys_info();
|
||||
}
|
||||
}
|
||||
else if(n==10) // [z,1,1500]
|
||||
{
|
||||
freq = get_zero_freq();
|
||||
if(IS_ZERO_BUF_VALID() && freq<=1504)
|
||||
{
|
||||
if(g_RxBuf[3]=='1')
|
||||
{
|
||||
search_zero(1,freq); // 顺时针搜索
|
||||
}
|
||||
else
|
||||
{
|
||||
search_zero(0,freq); // 逆时针搜索
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BEEP_Start(1500, 5, 5, 3);
|
||||
}
|
||||
}
|
||||
else if((n==17)&&(g_RxBuf[1]=='r'))
|
||||
{
|
||||
// [r,1,1500,108288]
|
||||
freq = get_run_freq();
|
||||
pulse = get_pulse();
|
||||
g_tMoto.sv_pulse = pulse;
|
||||
|
||||
if(g_RxBuf[3]=='1')
|
||||
{
|
||||
_dir = 1;
|
||||
g_tMoto.sv_pulse = -g_tMoto.sv_pulse;
|
||||
}
|
||||
else if(g_RxBuf[3]=='0')
|
||||
{
|
||||
_dir = 0;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
BEEP_Start(1500, 5, 5, 3);
|
||||
return ;
|
||||
}
|
||||
|
||||
if(g_tMoto.pv_pulse<g_tMoto.sv_pulse)
|
||||
{
|
||||
//MOTO_Start(freq, _dir, 123);
|
||||
MOTO_Start(freq, 0, 123);
|
||||
}
|
||||
else if(g_tMoto.pv_pulse>g_tMoto.sv_pulse)
|
||||
{
|
||||
//MOTO_Start(freq, _dir, 123);
|
||||
MOTO_Start(freq, 1, 123);
|
||||
}
|
||||
else
|
||||
{
|
||||
BEEP_Start(1500, 5, 5, 3);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BEEP_Start(1500, 5, 5, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------- End of file ---------------------------------
|
||||
447
User/app/src/main.c
Normal file
447
User/app/src/main.c
Normal file
@@ -0,0 +1,447 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 模块名称:main
|
||||
// 文件名称:main
|
||||
// 版本名称:V1.0
|
||||
// 文件说明:旋转样品杆主文件
|
||||
// 日期时间:2018年8月16日21点38分
|
||||
// 文件作者:Jackie Chan
|
||||
// 修改记录:
|
||||
// 版本号 日期 作者 说明
|
||||
// V1.0 2018.08.16 J.C 正式发布
|
||||
//
|
||||
// 公司名称:多场低温科技有限公司
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#include "bsp.h" /* 底层硬件驱动 */
|
||||
#include "bsp_key.h"
|
||||
#include "stdint.h"
|
||||
#include "main.h"
|
||||
|
||||
uint8_t Flag_100ms = 0;
|
||||
extern DIGITIAL_TUBE_T g_tTube;
|
||||
extern MOTO_T g_tMoto;
|
||||
#define IS_ZERO_BUF_VALID() (g_RxBuf[1] == 'z' && \
|
||||
g_RxBuf[2] == ',' && g_RxBuf[4] == ',' && \
|
||||
(g_RxBuf[3] == '1' || g_RxBuf[3] == '0'))
|
||||
#define IS_MF_VALID (g_RxBuf[1] == 'M' && g_RxBuf[2] == 'F')
|
||||
static void Delay_ms(uint16_t us)
|
||||
{
|
||||
uint16_t i;
|
||||
|
||||
/*
|
||||
CPU主频168MHz时,在内部Flash运行, MDK工程不优化。用台式示波器观测波形。
|
||||
循环次数为5时,SCL频率 = 1.78MHz (读耗时: 92ms, 读写正常,但是用示波器探头碰上就读写失败。时序接近临界)
|
||||
循环次数为10时,SCL频率 = 1.1MHz (读耗时: 138ms, 读速度: 118724B/s)
|
||||
循环次数为30时,SCL频率 = 440KHz, SCL高电平时间1.0us,SCL低电平时间1.2us
|
||||
|
||||
上拉电阻选择2.2K欧时,SCL上升沿时间约0.5us,如果选4.7K欧,则上升沿约1us
|
||||
|
||||
实际应用选择400KHz左右的速率即可
|
||||
*/
|
||||
for (i = 0; i < (300 * us); i++)
|
||||
;
|
||||
}
|
||||
void key1_task(void);
|
||||
void key2_task(void);
|
||||
void uart_msg_idle(void);
|
||||
// #include "bsp_adc.h"-
|
||||
// #include "delay.h"
|
||||
|
||||
// 初始化ADC
|
||||
// 这里我们仅以规则通道为例
|
||||
// 我们默认将开启通道0~3
|
||||
void Adc_Init(void)
|
||||
{
|
||||
ADC_InitTypeDef ADC_InitStructure;
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1, ENABLE); // 使能ADC1通道时钟
|
||||
|
||||
RCC_ADCCLKConfig(RCC_PCLK2_Div6); // 设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
|
||||
|
||||
// PA1 作为模拟通道输入引脚
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; // 模拟输入引脚
|
||||
GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||||
|
||||
ADC_DeInit(ADC1); // 复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值
|
||||
|
||||
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; // ADC工作模式:ADC1和ADC2工作在独立模式
|
||||
ADC_InitStructure.ADC_ScanConvMode = DISABLE; // 模数转换工作在单通道模式
|
||||
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; // 模数转换工作在单次转换模式
|
||||
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 转换由软件而不是外部触发启动
|
||||
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // ADC数据右对齐
|
||||
ADC_InitStructure.ADC_NbrOfChannel = 1; // 顺序进行规则转换的ADC通道的数目
|
||||
ADC_Init(ADC1, &ADC_InitStructure); // 根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器
|
||||
|
||||
ADC_Cmd(ADC1, ENABLE); // 使能指定的ADC1
|
||||
|
||||
ADC_ResetCalibration(ADC1); // 使能复位校准
|
||||
|
||||
while (ADC_GetResetCalibrationStatus(ADC1))
|
||||
; // 等待复位校准结束
|
||||
|
||||
ADC_StartCalibration(ADC1); // 开启AD校准
|
||||
|
||||
while (ADC_GetCalibrationStatus(ADC1))
|
||||
; // 等待校准结束
|
||||
|
||||
// ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能
|
||||
}
|
||||
// 获得ADC值
|
||||
// ch:通道值 0~3 ADC_Channel_1
|
||||
u16 Get_Adc(u8 ch)
|
||||
{
|
||||
// 设置指定ADC的规则组通道,一个序列,采样时间
|
||||
ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5); // ADC1,ADC通道,采样时间为239.5周期
|
||||
|
||||
ADC_SoftwareStartConvCmd(ADC1, ENABLE); // 使能指定的ADC1的软件转换启动功能
|
||||
|
||||
while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC))
|
||||
; // 等待转换结束
|
||||
|
||||
return ADC_GetConversionValue(ADC1); // 返回最近一次ADC1规则组的转换结果
|
||||
}
|
||||
|
||||
u16 Get_Adc_Average(u8 ch, u8 times)
|
||||
{
|
||||
u32 temp_val = 0;
|
||||
u8 t;
|
||||
for (t = 0; t < times; t++)
|
||||
{
|
||||
temp_val += Get_Adc(ch);
|
||||
Delay_ms(5);
|
||||
}
|
||||
return temp_val / times;
|
||||
}
|
||||
|
||||
u16 get_key4_adc(void)
|
||||
{
|
||||
u16 key4_adc = 0;
|
||||
u16 ad_value;
|
||||
|
||||
ad_value = Get_Adc_Average(ADC_Channel_1, 10);
|
||||
|
||||
key4_adc = ad_value;
|
||||
if (key4_adc > 3000)
|
||||
{
|
||||
key4_adc = 2; // 前进
|
||||
}
|
||||
else if (key4_adc <= 1200)
|
||||
{
|
||||
key4_adc = 1; // 后退
|
||||
}
|
||||
else if ((key4_adc > 1200) && (key4_adc <= 3000))
|
||||
{
|
||||
key4_adc = 0; // 后退
|
||||
}
|
||||
return key4_adc;
|
||||
}
|
||||
u16 get_key5_adc(void)
|
||||
{
|
||||
u16 key5_adc = 0;
|
||||
u16 ad_value;
|
||||
|
||||
ad_value = Get_Adc_Average(ADC_Channel_2, 10);
|
||||
|
||||
// electric_quantity_percent = ((ad_value*3.3/4096.0)-1.846)*100/0.52;
|
||||
key5_adc = (ad_value * 3.3 / 4096.0);
|
||||
|
||||
if (key5_adc >= 3000)
|
||||
{
|
||||
key5_adc = 1; // 前进
|
||||
}
|
||||
else if (key5_adc <= 1200)
|
||||
{
|
||||
key5_adc = 2; // 后退
|
||||
}
|
||||
else if ((key5_adc > 1200) && (key5_adc < 3000))
|
||||
{
|
||||
key5_adc = 0; // 后退
|
||||
}
|
||||
return key5_adc;
|
||||
}
|
||||
|
||||
void motor_dir(uint32_t freq, uint8_t _dir, int64_t _stpes)
|
||||
{
|
||||
// [r,1,1500,108288]
|
||||
|
||||
if (g_tTube.state == WORK)
|
||||
{
|
||||
if (_dir == 1)
|
||||
{
|
||||
_dir = 1;
|
||||
if (g_tMoto.sv_pulse + 100 < INT64_MAX)
|
||||
g_tMoto.sv_pulse = g_tMoto.sv_pulse + 100;
|
||||
}
|
||||
else if (_dir == 0)
|
||||
{
|
||||
_dir = 0;
|
||||
if (g_tMoto.sv_pulse - 100 > INT64_MIN)
|
||||
g_tMoto.sv_pulse = g_tMoto.sv_pulse - 100;
|
||||
}
|
||||
|
||||
if (g_tMoto.pv_pulse < g_tMoto.sv_pulse)
|
||||
{
|
||||
|
||||
if (g_tMoto.sv_pulse > INT64_MAX)
|
||||
{
|
||||
g_tMoto.sv_pulse = INT64_MAX;
|
||||
}
|
||||
else if (g_tMoto.sv_pulse <= INT64_MAX)
|
||||
{
|
||||
MOTO_Start(1500, 0, 100);
|
||||
}
|
||||
}
|
||||
else if (g_tMoto.pv_pulse > g_tMoto.sv_pulse)
|
||||
{
|
||||
if (g_tMoto.sv_pulse < INT64_MIN)
|
||||
{
|
||||
g_tMoto.sv_pulse = INT64_MIN;
|
||||
}
|
||||
else if (g_tMoto.sv_pulse >= INT64_MIN)
|
||||
{
|
||||
MOTO_Start(1500, 1, 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
int main(void)
|
||||
{
|
||||
uint8_t ucKeyCode;
|
||||
uint32_t freq = 1500;
|
||||
uint16_t motor_move1 = 0;
|
||||
uint32_t g_sysclk_src = 0, g_pll_mul = 0;
|
||||
// uint16_t motor_move2 = 0;
|
||||
|
||||
SCB->VTOR = 0x08008000;
|
||||
|
||||
/* === MCO 测试: PA8 输出 PLLCLK/2,示波器测量 PA8 === */
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
|
||||
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;
|
||||
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
|
||||
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
|
||||
GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||
RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_MCO) | RCC_CFGR_MCO_PLL;
|
||||
/* MCO 输出 PLL/2:72MHz 系统 = 36MHz, 48MHz 系统 = 24MHz */
|
||||
}
|
||||
|
||||
/* 运行时检测实际系统时钟 */
|
||||
{
|
||||
g_sysclk_src = RCC->CFGR & RCC_CFGR_SWS;
|
||||
if (g_sysclk_src == 0x08)
|
||||
{
|
||||
g_pll_mul = (RCC->CFGR & RCC_CFGR_PLLMULL) >> 18;
|
||||
g_pll_mul = g_pll_mul + 2;
|
||||
}
|
||||
}
|
||||
|
||||
bsp_Init(); /* 硬件初始化 */
|
||||
|
||||
/* 打印调试信息(需在串口初始化后) */
|
||||
{
|
||||
if (g_sysclk_src == 0x00)
|
||||
printf("SYSCLK = HSI 8MHz\r\n");
|
||||
else if (g_sysclk_src == 0x04)
|
||||
printf("SYSCLK = HSE\r\n");
|
||||
else if (g_sysclk_src == 0x08)
|
||||
{
|
||||
printf("PLL MUL = %u, PLL = 8MHz * %u = %uMHz\r\n", g_pll_mul, g_pll_mul, 8 * g_pll_mul);
|
||||
}
|
||||
printf("SystemCoreClock var = %lu\r\n", SystemCoreClock);
|
||||
printf("RCC->CFGR = 0x%08lX, PPRE1=%lu\r\n", RCC->CFGR, (RCC->CFGR >> 8) & 0x7);
|
||||
printf("TIM6 PSC = %u, ARR = %u\r\n", TIM6->PSC, TIM6->ARR);
|
||||
}
|
||||
|
||||
Adc_Init(); // ADC初始化
|
||||
BEEP_Start(freq, 20, 1, 1);
|
||||
|
||||
g_tTube.state = WORK;
|
||||
MOTO_Stop();
|
||||
|
||||
/* 主程序大循环 */
|
||||
while (1)
|
||||
{
|
||||
bsp_Idle(); /* CPU空闲时执行的函数,在 bsp.c */
|
||||
uart_msg_idle();
|
||||
if (Flag_100ms == 1)
|
||||
{
|
||||
Flag_100ms = 0;
|
||||
motor_move1 = get_key4_adc();
|
||||
// motor_move2 = get_key5_adc();
|
||||
if (motor_move1 == 1) // key4
|
||||
{
|
||||
motor_move1 = 0;
|
||||
// 前进
|
||||
motor_dir(1500, 0, 3000);
|
||||
}
|
||||
else if (motor_move1 == 2)
|
||||
{
|
||||
motor_move1 = 0;
|
||||
// 后退
|
||||
motor_dir(1500, 1, 3000);
|
||||
}
|
||||
}
|
||||
/* 处理按键事件 */
|
||||
ucKeyCode = bsp_GetKey();
|
||||
|
||||
if (ucKeyCode > 0)
|
||||
{
|
||||
/* 有键按下 */
|
||||
switch (ucKeyCode) // key6
|
||||
{
|
||||
case KEY_DOWN_K6: // key6 短按
|
||||
{
|
||||
MOTO_ZorePos();
|
||||
break;
|
||||
}
|
||||
|
||||
case KEY_DOWN_K1: // Key1 短按
|
||||
{
|
||||
BEEP_KeyTone(); // 按键提示音
|
||||
bsp_ToogleDispMode();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void send_sv_2_uart(void)
|
||||
{
|
||||
float angle = g_tTube.pulse * 360.0f / STEP_PER_LAP; // 22 * 16 * 24
|
||||
printf("[w,%.2f]\r\n", angle);
|
||||
}
|
||||
|
||||
void print_sys_info(void)
|
||||
{
|
||||
printf("\r\n");
|
||||
printf("----------------------------->\r\n");
|
||||
printf("-> 设备名称:无限旋转控制器\r\n");
|
||||
printf("-> software verson: V1.0\r\n");
|
||||
printf("-> compile time: %s\r\n", __TIME__);
|
||||
printf("-> compile date: %s\r\n", __DATE__);
|
||||
printf("-> [多场低温科技有限公司]\r\n");
|
||||
printf("------------------------------\r\n");
|
||||
printf("->可用命令:\r\n");
|
||||
printf("1. [s] // 停止电机转动\r\n");
|
||||
printf("2. [?] // 读取当前位置角度\r\n");
|
||||
printf("3. [z] // 设置当前位置为零点\r\n");
|
||||
printf("4. [MF] // 打印系统信息\r\n");
|
||||
printf("5. [r:10:360] // 转动命令,10为转动角速度,360为目标角度\r\n");
|
||||
printf("6. [rr:10:20] // 转动命令,10为转动角速度,20为相对转动角度\r\n");
|
||||
printf("<-----------------------------\r\n");
|
||||
}
|
||||
|
||||
void uart_msg_idle(void)
|
||||
{
|
||||
uint8_t n = 0;
|
||||
float freq = 0;
|
||||
float pulse = 0;
|
||||
float angle = 0;
|
||||
|
||||
if (g_ucRxRcvNewFlag)
|
||||
{
|
||||
g_ucRxRcvNewFlag = 0;
|
||||
|
||||
n = strlen((char *)g_RxBuf);
|
||||
if (n == 3)
|
||||
{
|
||||
switch (g_RxBuf[1])
|
||||
{
|
||||
case '?':
|
||||
send_sv_2_uart();
|
||||
break;
|
||||
case 's':
|
||||
MOTO_Stop();
|
||||
break;
|
||||
case 'z':
|
||||
MOTO_ZorePos();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (n == 4)
|
||||
{
|
||||
if (IS_MF_VALID)
|
||||
{
|
||||
print_sys_info();
|
||||
}
|
||||
}
|
||||
else if (g_RxBuf[1] == 'r')
|
||||
{
|
||||
// [r,10,100] // 10°/s 转到100°
|
||||
if (sscanf((char *)g_RxBuf, "[r:%f:%f]", &freq, &angle) == 2)
|
||||
{
|
||||
if (freq < 0.01f)
|
||||
freq = 0.01f;
|
||||
else if (freq > MAX_SPEED)
|
||||
freq = MAX_SPEED;
|
||||
pulse = (angle / 360) * STEP_PER_LAP; // angle所有需要的脉冲
|
||||
freq = freq * (STEP_PER_LAP / 360.0f); // 角速度所需要的脉冲频率
|
||||
g_tMoto.sv_pulse = (int64_t)pulse;
|
||||
|
||||
printf("[r] freq=%lu, angle=%f, pulse=%ld, sv_pulse=%lld\r\n", (unsigned long)freq, angle, (long)pulse, g_tMoto.sv_pulse);
|
||||
printf("TIM6 before start: PSC=%u, ARR=%u\r\n", TIM6->PSC, TIM6->ARR);
|
||||
|
||||
if (g_tMoto.pv_pulse < g_tMoto.sv_pulse)
|
||||
{
|
||||
MOTO_Start(freq, 0, 123);
|
||||
}
|
||||
else if (g_tMoto.pv_pulse > g_tMoto.sv_pulse)
|
||||
{
|
||||
MOTO_Start(freq, 1, 123);
|
||||
}
|
||||
else
|
||||
{
|
||||
BEEP_Start(1500, 5, 5, 3);
|
||||
}
|
||||
printf("TIM6 after start: PSC=%u, ARR=%u\r\n", TIM6->PSC, TIM6->ARR);
|
||||
}
|
||||
else if (sscanf((char *)g_RxBuf, "[rr:%f:%f]", &freq, &angle) == 2)
|
||||
{
|
||||
if (pulse < 0.01f)
|
||||
pulse = 0.01f;
|
||||
else if (pulse > MAX_SPEED)
|
||||
pulse = MAX_SPEED;
|
||||
pulse = (angle / 360) * STEP_PER_LAP; // angle所有需要的脉冲
|
||||
freq = freq * (STEP_PER_LAP / 360.0f); // 角速度所需要的脉冲频率
|
||||
g_tMoto.sv_pulse += (int64_t)pulse;
|
||||
|
||||
printf("[rr] freq=%lu, angle=%f, pulse=%ld, sv_pulse=%lld\r\n", (unsigned long)freq, angle, (long)pulse, g_tMoto.sv_pulse);
|
||||
printf("TIM6 before start: PSC=%u, ARR=%u\r\n", TIM6->PSC, TIM6->ARR);
|
||||
|
||||
if (g_tMoto.pv_pulse < g_tMoto.sv_pulse)
|
||||
{
|
||||
MOTO_Start(freq, 0, 123);
|
||||
}
|
||||
else if (g_tMoto.pv_pulse > g_tMoto.sv_pulse)
|
||||
{
|
||||
MOTO_Start(freq, 1, 123);
|
||||
}
|
||||
else
|
||||
{
|
||||
BEEP_Start(1500, 5, 5, 3);
|
||||
}
|
||||
printf("TIM6 after start: PSC=%u, ARR=%u\r\n", TIM6->PSC, TIM6->ARR);
|
||||
}
|
||||
else
|
||||
{
|
||||
BEEP_Start(1500, 5, 5, 3);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BEEP_Start(1500, 5, 5, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------- End of file ---------------------------------
|
||||
117
User/bsp/bsp.c
Normal file
117
User/bsp/bsp.c
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
*
|
||||
* 模块名称 : BSP模块(For STM32F103)
|
||||
* 文件名称 : bsp.c
|
||||
* 版 本 : V1.0
|
||||
* 说 明 : 这是硬件底层驱动程序模块的主文件。主要提供 bsp_Init()函数供主程序调用。主程序的每个c文件可以在开
|
||||
* 头 添加 #include "bsp.h" 来包含所有的外设驱动模块。
|
||||
*
|
||||
* 修改记录 :
|
||||
* 版本号 日期 作者 说明
|
||||
* V1.0 2015-09-01 armfly 正式发布
|
||||
*
|
||||
* Copyright (C), 2015-2020, 安富莱电子 www.armfly.com
|
||||
*
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#include "bsp.h"
|
||||
|
||||
uint32_t RxCount = 0;
|
||||
uint32_t TxCount = 0;
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_Init
|
||||
* 功能说明: 初始化硬件设备。只需要调用一次。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。
|
||||
* 全局变量。
|
||||
* 形 参:无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void bsp_Init(void)
|
||||
{
|
||||
/*
|
||||
由于ST固件库的启动文件已经执行了CPU系统时钟的初始化,所以不必再次重复配置系统时钟。
|
||||
启动文件配置了CPU主时钟频率、内部Flash访问速度和可选的外部SRAM FSMC初始化。
|
||||
|
||||
系统时钟缺省配置为72MHz,如果需要更改,可以修改 system_stm32f103.c 文件
|
||||
*/
|
||||
|
||||
/* 优先级分组设置为4 */
|
||||
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
|
||||
|
||||
bsp_InitKey(); /* 初始化按键 */
|
||||
|
||||
bsp_InitTimer(); /* 初始化系统滴答定时器 (此函数会开中断) */
|
||||
|
||||
/* 初始化串口驱动 */
|
||||
USART_Config();
|
||||
/* 配置使用DMA模式 */
|
||||
USARTx_DMA_Config();
|
||||
USART_DMACmd(DEBUG_USARTx, USART_DMAReq_Rx, ENABLE);
|
||||
|
||||
BEEP_InitHard(); /* 配置蜂鸣器GPIO */
|
||||
|
||||
bsp_InitI2C(); /* 配置I2C总线 */
|
||||
bsp_InitDigitalTube(); // 初始化数码管控制端口
|
||||
|
||||
bsp_Init_Drv8880_Hard();
|
||||
bsp_InitStepMoto();
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_RunPer10ms
|
||||
* 功能说明: 该函数每隔10ms被Systick中断调用1次。详见 bsp_timer.c的定时中断服务程序。一些处理时间要求不严格的
|
||||
* 任务可以放在此函数。比如:按键扫描、蜂鸣器鸣叫控制等。
|
||||
* 形 参:无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void bsp_RunPer10ms(void)
|
||||
{
|
||||
bsp_KeyScan(); /* 每10ms扫描按键一次 */
|
||||
|
||||
BEEP_Pro(); /* 蜂鸣器定时处理 */
|
||||
|
||||
// bsp_FpgaPowerMainLoop(30); // 给FPAGA延迟供电,延迟时间位30*10ms
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_RunPer1ms
|
||||
* 功能说明: 该函数每隔1ms被Systick中断调用1次。详见 bsp_timer.c的定时中断服务程序。一些需要周期性处理的事务
|
||||
* 可以放在此函数。比如:触摸坐标扫描。
|
||||
* 形 参: 无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void bsp_RunPer1ms(void)
|
||||
{
|
||||
bsp_DigitalTubeMainLoop();
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_Idle
|
||||
* 功能说明: 空闲时执行的函数。一般主程序在for和while循环程序体中需要插入 CPU_IDLE() 宏来调用本函数。
|
||||
* 本函数缺省为空操作。用户可以添加喂狗、设置CPU进入休眠模式的功能。
|
||||
* 形 参:无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void bsp_Idle(void)
|
||||
{
|
||||
/* --- 喂狗 */
|
||||
|
||||
/* --- 让CPU进入休眠,由Systick定时中断唤醒或者其他中断唤醒 */
|
||||
|
||||
/* 例如 emWin 图形库,可以插入图形库需要的轮询函数 */
|
||||
// GUI_Exec();
|
||||
|
||||
/* 例如 uIP 协议,可以插入uip轮询函数 */
|
||||
}
|
||||
|
||||
/***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
|
||||
83
User/bsp/bsp.h
Normal file
83
User/bsp/bsp.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
*
|
||||
* 模块名称 : BSP模块
|
||||
* 文件名称 : bsp.h
|
||||
* 说 明 : 这是底层驱动模块所有的h文件的汇总文件。 应用程序只需 #include bsp.h 即可,
|
||||
* 不需要#include 每个模块的 h 文件
|
||||
*
|
||||
* Copyright (C), 2013-2014, 安富莱电子 www.armfly.com
|
||||
*
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _BSP_H_
|
||||
#define _BSP_H_
|
||||
|
||||
#define STM32_V4
|
||||
//#define STM32_X2
|
||||
|
||||
/* 检查是否定义了开发板型号 */
|
||||
#if !defined (STM32_V4) && !defined (STM32_X2)
|
||||
#error "Please define the board model : STM32_X2 or STM32_V4"
|
||||
#endif
|
||||
|
||||
/* 定义 BSP 版本号 */
|
||||
#define __STM32F1_BSP_VERSION "1.1"
|
||||
|
||||
/* CPU空闲时执行的函数 */
|
||||
//#define CPU_IDLE() bsp_Idle()
|
||||
|
||||
/* 开关全局中断的宏 */
|
||||
#define ENABLE_INT() __set_PRIMASK(0) /* 使能全局中断 */
|
||||
#define DISABLE_INT() __set_PRIMASK(1) /* 禁止全局中断 */
|
||||
|
||||
/* 这个宏仅用于调试阶段排错 */
|
||||
#define BSP_Printf printf
|
||||
//#define BSP_Printf(...)
|
||||
|
||||
#include "stm32f10x.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
//#include "bsp_led.h"
|
||||
#include "bsp_timer.h"
|
||||
#include "bsp_key.h"
|
||||
|
||||
#include "bsp_usart_dma.h"
|
||||
#include "bsp_tim_pwm.h"
|
||||
#include "bsp_beep.h"
|
||||
|
||||
#include "bsp_digital_tube.h"
|
||||
#include "bsp_i2c_gpio.h"
|
||||
#include "bsp_eeprom_24xx.h"
|
||||
#include "bsp_drv8880.h"
|
||||
#include "bsp_step_moto.h"
|
||||
//#include "bsp_adc.h"
|
||||
//#include "sys.h" /* 底层硬件驱动 */
|
||||
//uint8_t Flag_100ms;
|
||||
extern uint8_t Flag_100ms;
|
||||
extern uint32_t RxCount ;
|
||||
extern uint32_t TxCount ;
|
||||
|
||||
/* 提供给其他C文件调用的函数 */
|
||||
void bsp_Init(void);
|
||||
void bsp_Idle(void);
|
||||
|
||||
|
||||
#define MAX_SPEED 400
|
||||
#define STEP_PER_LAP 8461
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
|
||||
39
User/bsp/inc/bsp_beep.h
Normal file
39
User/bsp/inc/bsp_beep.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
*
|
||||
* 模块名称 : 蜂鸣器模块
|
||||
* 文件名称 : bsp_beep.h
|
||||
* 版 本 : V1.0
|
||||
* 说 明 : 头文件
|
||||
*
|
||||
* Copyright (C), 2012-2013, 安富莱电子 www.armfly.com
|
||||
*
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __BSP_BEEP_H
|
||||
#define __BSP_BEEP_H
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct _BEEP_T
|
||||
{
|
||||
uint8_t ucEnalbe;
|
||||
uint8_t ucState;
|
||||
uint16_t usBeepTime;
|
||||
uint16_t usStopTime;
|
||||
uint16_t usCycle;
|
||||
uint16_t usCount;
|
||||
uint16_t usCycleCount;
|
||||
uint32_t uiFreq;
|
||||
}BEEP_T;
|
||||
|
||||
/* 供外部调用的函数声明 */
|
||||
void BEEP_InitHard(void);
|
||||
void BEEP_Start(uint32_t _uiFreq, uint16_t _usBeepTime, uint16_t _usStopTime, uint16_t _usCycle);
|
||||
void BEEP_Stop(void);
|
||||
void BEEP_KeyTone(void);
|
||||
void BEEP_Pro(void);
|
||||
|
||||
#endif
|
||||
|
||||
/***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
|
||||
29
User/bsp/inc/bsp_channel_realy.h
Normal file
29
User/bsp/inc/bsp_channel_realy.h
Normal file
@@ -0,0 +1,29 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 模块名称:通道继电器选择模块
|
||||
// 文件名称:bsp_channel_relay
|
||||
// 版本名称:V1.0
|
||||
// 文件说明:头文件
|
||||
// 日期时间:2018年8月8日19点52分
|
||||
// 文件作者:Jackie Chan
|
||||
// 修改记录:
|
||||
// 版本号 日期 作者 说明
|
||||
// V1.0 2018.08.08 J.C 正式发布
|
||||
//
|
||||
// 公司名称:多场低温科技有限公司
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifndef __BSP_CHANNEL_RELAY_H__
|
||||
#define __BSP_CHANNEL_RELAY_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// 供外面调用的函数声明
|
||||
void bsp_InitChannelRelay(void);
|
||||
void bsp_RealyAllOff(void);
|
||||
void bsp_RelayOn(uint8_t _ch);
|
||||
|
||||
#endif
|
||||
|
||||
//-------------------------------- End of file ---------------------------------
|
||||
|
||||
76
User/bsp/inc/bsp_digital_tube.h
Normal file
76
User/bsp/inc/bsp_digital_tube.h
Normal file
@@ -0,0 +1,76 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 模块名称:数码管驱动模块
|
||||
// 文件名称:bsp_digital_tube
|
||||
// 版本名称:V1.0
|
||||
// 文件说明:头文件
|
||||
// 日期时间:2018年8月15日20点02分
|
||||
// 文件作者:Jackie Chan
|
||||
// 修改记录:
|
||||
// 版本号 日期 作者 说明
|
||||
// V1.0 2018.08.15 J.C 正式发布
|
||||
//
|
||||
// 公司名称:多场低温科技有限公司
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifndef __BSP_DIGITAL_TUBE__H__
|
||||
#define __BSP_DIGITAL_TUBE__H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NO_0 = 0,
|
||||
NO_1,
|
||||
NO_2,
|
||||
NO_3,
|
||||
NO_4,
|
||||
NO_5,
|
||||
NO_6,
|
||||
NO_7,
|
||||
NO_8,
|
||||
NO_9,
|
||||
NO__,
|
||||
NO_NULL,
|
||||
}SEG_NUM_E;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
IDLE, // 空闲模式
|
||||
WORK, // 工作模式
|
||||
SEARCH, // 搜索模式
|
||||
}STATE_E;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MODE_PULSE, // 脉冲显示模式
|
||||
MODE_ANGLE, // 角度显示模式
|
||||
}MODE_E;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DIR_CW, // 样品杆从上往下看,顺时针旋转(+)
|
||||
DIR_CCW, // 样品杆从上往下看,逆时针旋转(-)
|
||||
}DIR_E;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char buf[9]; // 8个数码管的刷新缓冲区
|
||||
uint8_t disp_mode; // 显示模式,角度显示和脉冲数量显示
|
||||
uint8_t cnt; // 数码管轮询显示计数
|
||||
uint8_t state; // 工作状态,空闲模式、工作模式
|
||||
uint8_t dir; // 电机旋转方向,样品杆从上往下看,顺时针(+)还是逆时针(-)
|
||||
int32_t pulse; // 电机转动过的脉冲数量,+表示顺时针累积脉冲,-表示逆时针累积
|
||||
int32_t tim_pulse_cnt; // 定时器计数的脉冲数量,每1ms更新到上面pluse中
|
||||
int32_t angle; // 电机转动过的角度
|
||||
}DIGITIAL_TUBE_T;
|
||||
|
||||
void bsp_InitDigitalTube(void);
|
||||
void bsp_DigitalTubeMainLoop(void);
|
||||
void bsp_TubeTest(uint8_t _com, uint8_t _seg);
|
||||
void bsp_UpdateDisplayBuf(void);
|
||||
void bsp_ToogleDispMode(void);
|
||||
void bsp_ToogleStateMode(void);
|
||||
|
||||
#endif
|
||||
//-------------------------------- End of file ---------------------------------
|
||||
45
User/bsp/inc/bsp_drv8880.h
Normal file
45
User/bsp/inc/bsp_drv8880.h
Normal file
@@ -0,0 +1,45 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 模块名称:步进电机芯片DRV8880驱动模块
|
||||
// 文件名称:bsp_drv8880
|
||||
// 版本名称:V1.0
|
||||
// 文件说明:头文件
|
||||
// 日期时间:2018年8月17日16点23分
|
||||
// 文件作者:Jackie Chan
|
||||
// 修改记录:
|
||||
// 版本号 日期 作者 说明
|
||||
// V1.0 2018.08.17 J.C 正式发布
|
||||
//
|
||||
// 公司名称:多场低温科技有限公司
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifndef __BSP_DRV8880_H__
|
||||
#define __BSP_DRV8880_H__
|
||||
|
||||
#include "bsp.h"
|
||||
|
||||
// typedef enum
|
||||
// {
|
||||
// DISABLE = 0,
|
||||
// ENABLE = !DISABLE
|
||||
// }BoolState;
|
||||
|
||||
// 细分入口参数
|
||||
typedef enum
|
||||
{
|
||||
STEP_FULL = 0, // Full step with 71% current
|
||||
STEP_1_2_NC, // Non-circular 1/2 step
|
||||
STEP_1_2, // 1/2 step
|
||||
STEP_1_4, // 1/4 step
|
||||
STEP_1_8, // 1/8 step
|
||||
STEP_1_16 // 1/16 step
|
||||
}MICRO_STEPPING_E;
|
||||
|
||||
void bsp_Init_Drv8880_Hard(void);
|
||||
void bsp_drv8880_enable_config(FunctionalState en);
|
||||
void bsp_drv8880_microstep_config(MICRO_STEPPING_E step);
|
||||
void bsp_drv8880_config_dir(DIR_E dir);
|
||||
|
||||
#endif
|
||||
|
||||
//-------------------------------- End of file ---------------------------------
|
||||
56
User/bsp/inc/bsp_eeprom_24xx.h
Normal file
56
User/bsp/inc/bsp_eeprom_24xx.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
*
|
||||
* 模块名称 : 串行EEPROM 24xx02驱动模块
|
||||
* 文件名称 : bsp_eeprom_24xx.h
|
||||
* 版 本 : V1.0
|
||||
* 说 明 : 头文件
|
||||
*
|
||||
* 修改记录 :
|
||||
* 版本号 日期 作者 说明
|
||||
* v1.0 2012-10-12 armfly ST固件库版本 V2.1.0
|
||||
*
|
||||
* Copyright (C), 2012-2013, 安富莱电子 www.armfly.com
|
||||
*
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _BSP_EEPROM_24XX_H
|
||||
#define _BSP_EEPROM_24XX_H
|
||||
#include <stdint.h>
|
||||
|
||||
//#define AT24C02
|
||||
#define AT24C128
|
||||
//#define AT24C256
|
||||
|
||||
#ifdef AT24C02
|
||||
#define EE_MODEL_NAME "AT24C02"
|
||||
#define EE_DEV_ADDR 0xA0 /* 设备地址 */
|
||||
#define EE_PAGE_SIZE 8 /* 页面大小(字节) */
|
||||
#define EE_SIZE 256 /* 总容量(字节) */
|
||||
#define EE_ADDR_BYTES 1 /* 地址字节个数 */
|
||||
#endif
|
||||
|
||||
#ifdef AT24C128
|
||||
#define EE_MODEL_NAME "AT24C128"
|
||||
#define EE_DEV_ADDR 0xA0 /* 设备地址 */
|
||||
#define EE_PAGE_SIZE 64 /* 页面大小(字节) */
|
||||
#define EE_SIZE (16*1024) /* 总容量(字节) */
|
||||
#define EE_ADDR_BYTES 2 /* 地址字节个数 */
|
||||
#endif
|
||||
|
||||
#ifdef AT24C256
|
||||
#define EE_MODEL_NAME "AT24C256"
|
||||
#define EE_DEV_ADDR 0xA0 /* 设备地址 */
|
||||
#define EE_PAGE_SIZE 64 /* 页面大小(字节) */
|
||||
#define EE_SIZE (32*1024) /* 总容量(字节) */
|
||||
#define EE_ADDR_BYTES 2 /* 地址字节个数 */
|
||||
#endif
|
||||
|
||||
uint8_t ee_CheckOk(void);
|
||||
uint8_t ee_ReadBytes(uint8_t *_pReadBuf, uint16_t _usAddress, uint16_t _usSize);
|
||||
uint8_t ee_WriteBytes(uint8_t *_pWriteBuf, uint16_t _usAddress, uint16_t _usSize);
|
||||
|
||||
#endif
|
||||
|
||||
/***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
|
||||
29
User/bsp/inc/bsp_fpga_power.h
Normal file
29
User/bsp/inc/bsp_fpga_power.h
Normal file
@@ -0,0 +1,29 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 模块名称:FPGA供电控制驱动模块
|
||||
// 文件名称:bsp_fpag_power.h
|
||||
// 版本名称:V1.0
|
||||
// 文件说明:头文件
|
||||
// 日期时间:2018年8月8日17点52分
|
||||
// 文件作者:Jackie Chan
|
||||
// 修改记录:
|
||||
// 版本号 日期 作者 说明
|
||||
// V1.0 2018.08.08 J.C 正式发布
|
||||
//
|
||||
// 公司名称:多场低温科技有限公司
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifndef __BSP_FPGA_POWER_H__
|
||||
#define __BSP_FPGA_POWER_H__
|
||||
|
||||
#include "bsp.h"
|
||||
|
||||
// 供外面调用的函数声明
|
||||
void bsp_InitFpgaPower(void);
|
||||
void bsp_FpgaPowerCmd(FunctionalState _NewState);
|
||||
void bsp_FpgaPowerMainLoop(uint16_t _delay_n_10ms);
|
||||
|
||||
#endif
|
||||
|
||||
//-------------------------------- End of file ---------------------------------
|
||||
|
||||
30
User/bsp/inc/bsp_i2c_gpio.h
Normal file
30
User/bsp/inc/bsp_i2c_gpio.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
*
|
||||
* 模块名称 : I2C总线驱动模块
|
||||
* 文件名称 : bsp_i2c_gpio.h
|
||||
* 版 本 : V1.0
|
||||
* 说 明 : 头文件。
|
||||
*
|
||||
* Copyright (C), 2012-2013, 安富莱电子 www.armfly.com
|
||||
*
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _BSP_I2C_GPIO_H
|
||||
#define _BSP_I2C_GPIO_H
|
||||
|
||||
#define I2C_WR 0 /* 写控制bit */
|
||||
#define I2C_RD 1 /* 读控制bit */
|
||||
|
||||
void bsp_InitI2C(void);
|
||||
void i2c_Start(void);
|
||||
void i2c_Stop(void);
|
||||
void i2c_SendByte(uint8_t _ucByte);
|
||||
uint8_t i2c_ReadByte(void);
|
||||
uint8_t i2c_WaitAck(void);
|
||||
void i2c_Ack(void);
|
||||
void i2c_NAck(void);
|
||||
uint8_t i2c_CheckDevice(uint8_t _Address);
|
||||
|
||||
#endif
|
||||
177
User/bsp/inc/bsp_key.h
Normal file
177
User/bsp/inc/bsp_key.h
Normal file
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
*
|
||||
* 模块名称 : 按键驱动模块
|
||||
* 文件名称 : bsp_key.h
|
||||
* 版 本 : V1.0
|
||||
* 说 明 : 头文件
|
||||
*
|
||||
* Copyright (C), 2013-2014, 安富莱电子 www.armfly.com
|
||||
*
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __BSP_KEY_H
|
||||
#define __BSP_KEY_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define KEY_COUNT 3
|
||||
|
||||
/* 根据应用程序的功能重命名按键宏 */
|
||||
#define KEY_DOWN_K6 KEY_1_DOWN
|
||||
#define KEY_UP_K6 KEY_1_UP
|
||||
#define KEY_LONG_K6 KEY_1_LONG
|
||||
|
||||
#define KEY_DOWN_K1 KEY_2_DOWN
|
||||
#define KEY_UP_K1 KEY_2_UP
|
||||
#define KEY_LONG_K1 KEY_2_LONG
|
||||
|
||||
#define KEY_DOWN_K2 KEY_3_DOWN
|
||||
#define KEY_UP_K2 KEY_3_UP
|
||||
#define KEY_LONG_K2 KEY_3_LONG
|
||||
|
||||
#define KEY_DOWN_K4 KEY_4_DOWN /* 上 */
|
||||
#define KEY_UP_K4 KEY_4_UP
|
||||
#define KEY_LONG_K4 KEY_4_LONG
|
||||
|
||||
#define KEY_DOWN_K5 KEY_5_DOWN /* 下 */
|
||||
#define KEY_UP_K5 KEY_5_UP
|
||||
#define KEY_LONG_K5 KEY_5_LONG
|
||||
|
||||
#define KEY_DOWN_K3 KEY_6_DOWN /* 左 */
|
||||
#define KEY_UP_K3 KEY_6_UP
|
||||
#define KEY_LONG_K3 KEY_6_LONG
|
||||
|
||||
#define KEY_DOWN_K7 KEY_7_DOWN /* 右 */
|
||||
#define KEY_UP_K7 KEY_7_UP
|
||||
#define KEY_LONG_K7 KEY_7_LONG
|
||||
|
||||
#define KEY_DOWN_K8 KEY_8_DOWN /* ok */
|
||||
#define KEY_UP_K8 KEY_8_UP
|
||||
#define KEY_LONG_K8 KEY_8_LONG
|
||||
|
||||
#define SYS_DOWN_K1K2 KEY_9_DOWN /* K1 K2 组合键 */
|
||||
#define SYS_UP_K1K2 KEY_9_UP
|
||||
#define SYS_LONG_K1K2 KEY_9_LONG
|
||||
|
||||
#define SYS_DOWN_K2K3 KEY_10_DOWN /* K2 K3 组合键 */
|
||||
#define SYS_UP_K2K3 KEY_10_UP
|
||||
#define SYS_LONG_K2K3 KEY_10_LONG
|
||||
|
||||
/* 按键ID, 主要用于bsp_KeyState()函数的入口参数 */
|
||||
typedef enum
|
||||
{
|
||||
KID_K1 = 0,
|
||||
KID_K2,
|
||||
KID_K3,
|
||||
KID_K4,
|
||||
KID_K5,
|
||||
KID_K6,
|
||||
KID_K7,
|
||||
KID_K8
|
||||
}KEY_ID_E;
|
||||
|
||||
/*
|
||||
按键滤波时间50ms, 单位10ms。
|
||||
只有连续检测到50ms状态不变才认为有效,包括弹起和按下两种事件
|
||||
即使按键电路不做硬件滤波,该滤波机制也可以保证可靠地检测到按键事件
|
||||
*/
|
||||
#define KEY_FILTER_TIME 1
|
||||
#define KEY_LONG_TIME 100 /* 单位10ms, 持续1秒,认为长按事件 */
|
||||
|
||||
/*
|
||||
每个按键对应1个全局的结构体变量。
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/* 下面是一个函数指针,指向判断按键手否按下的函数 */
|
||||
uint8_t (*IsKeyDownFunc)(void); /* 按键按下的判断函数,1表示按下 */
|
||||
|
||||
uint8_t Count; /* 滤波器计数器 */
|
||||
uint16_t LongCount; /* 长按计数器 */
|
||||
uint16_t LongTime; /* 按键按下持续时间, 0表示不检测长按 */
|
||||
uint8_t State; /* 按键当前状态(按下还是弹起) */
|
||||
uint8_t RepeatSpeed; /* 连续按键周期 */
|
||||
uint8_t RepeatCount; /* 连续按键计数器 */
|
||||
}KEY_T;
|
||||
|
||||
/*
|
||||
定义键值代码, 必须按如下次序定时每个键的按下、弹起和长按事件
|
||||
|
||||
推荐使用enum, 不用#define,原因:
|
||||
(1) 便于新增键值,方便调整顺序,使代码看起来舒服点
|
||||
(2) 编译器可帮我们避免键值重复。
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
KEY_NONE = 0, /* 0 表示按键事件 */
|
||||
|
||||
KEY_1_DOWN, /* 1键按下 */
|
||||
KEY_1_UP, /* 1键弹起 */
|
||||
KEY_1_LONG, /* 1键长按 */ //3
|
||||
|
||||
KEY_2_DOWN, /* 2键按下 */
|
||||
KEY_2_UP, /* 2键弹起 */
|
||||
KEY_2_LONG, /* 2键长按 *///6
|
||||
|
||||
KEY_3_DOWN, /* 3键按下 */
|
||||
KEY_3_UP, /* 3键弹起 */
|
||||
KEY_3_LONG, /* 3键长按 */
|
||||
|
||||
KEY_4_DOWN, /* 4键按下 */
|
||||
KEY_4_UP, /* 4键弹起 */
|
||||
KEY_4_LONG, /* 4键长按 */
|
||||
|
||||
KEY_5_DOWN, /* 5键按下 */
|
||||
KEY_5_UP, /* 5键弹起 */
|
||||
KEY_5_LONG, /* 5键长按 */
|
||||
|
||||
KEY_6_DOWN, /* 6键按下 */
|
||||
KEY_6_UP, /* 6键弹起 */
|
||||
KEY_6_LONG, /* 6键长按 */
|
||||
|
||||
KEY_7_DOWN, /* 7键按下 */
|
||||
KEY_7_UP, /* 7键弹起 */
|
||||
KEY_7_LONG, /* 7键长按 */
|
||||
|
||||
KEY_8_DOWN, /* 8键按下 */
|
||||
KEY_8_UP, /* 8键弹起 */
|
||||
KEY_8_LONG, /* 8键长按 */
|
||||
|
||||
/* 组合键 */
|
||||
KEY_9_DOWN, /* 9键按下 */
|
||||
KEY_9_UP, /* 9键弹起 */
|
||||
KEY_9_LONG, /* 9键长按 */
|
||||
|
||||
KEY_10_DOWN, /* 10键按下 */
|
||||
KEY_10_UP, /* 10键弹起 */
|
||||
KEY_10_LONG, /* 10键长按 */
|
||||
}KEY_ENUM;
|
||||
|
||||
/* 按键FIFO用到变量 */
|
||||
#define KEY_FIFO_SIZE 10
|
||||
typedef struct
|
||||
{
|
||||
uint8_t Buf[KEY_FIFO_SIZE]; /* 键值缓冲区 */
|
||||
uint8_t Read; /* 缓冲区读指针1 */
|
||||
uint8_t Write; /* 缓冲区写指针 */
|
||||
uint8_t Read2; /* 缓冲区读指针2 */
|
||||
}KEY_FIFO_T;
|
||||
|
||||
/* 供外部调用的函数声明 */
|
||||
void bsp_InitKey(void);
|
||||
void bsp_KeyScan(void);
|
||||
void bsp_PutKey(uint8_t _KeyCode);
|
||||
uint8_t bsp_GetKey(void);
|
||||
uint8_t bsp_GetKey2(void);
|
||||
uint8_t bsp_GetKeyState(KEY_ID_E _ucKeyID);
|
||||
void bsp_SetKeyParam(uint8_t _ucKeyID, uint16_t _LongTime, uint8_t _RepeatSpeed);
|
||||
void bsp_ClearKey(void);
|
||||
|
||||
uint8_t IsKeyDown2(void);
|
||||
uint8_t IsKeyDown3(void);
|
||||
|
||||
#endif
|
||||
|
||||
/***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
|
||||
31
User/bsp/inc/bsp_led.h
Normal file
31
User/bsp/inc/bsp_led.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
*
|
||||
* 模块名称 : LED指示灯驱动模块
|
||||
* 文件名称 : bsp_led.h
|
||||
* 版 本 : V1.0
|
||||
* 说 明 : 头文件
|
||||
*
|
||||
* Copyright (C), 2013-2014, 安富莱电子 www.armfly.com
|
||||
*
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __BSP_LED_H
|
||||
#define __BSP_LED_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* 供外部调用的函数声明 */
|
||||
void bsp_InitLed(void);
|
||||
void bsp_LedOn(uint8_t _no);
|
||||
void bsp_LedOff(uint8_t _no);
|
||||
void bsp_LedToggle(uint8_t _no);
|
||||
uint8_t bsp_IsLedOn(uint8_t _no);
|
||||
void bsp_LedAllOff(void);
|
||||
void bsp_ChannelSelect(uint8_t _ch);
|
||||
void bsp_ResSelect(uint8_t _res);
|
||||
|
||||
#endif
|
||||
|
||||
/***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
|
||||
41
User/bsp/inc/bsp_res.h
Normal file
41
User/bsp/inc/bsp_res.h
Normal file
@@ -0,0 +1,41 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 模块名称:压电位移控制器串联电阻驱动模块
|
||||
// 文件名称:bsp_res.h
|
||||
// 版本名称:V1.0
|
||||
// 文件说明:头文件
|
||||
// 日期时间:2018年8月8日15点14分
|
||||
// 文件作者:Jackie Chan
|
||||
// 修改记录:
|
||||
// 版本号 日期 作者 说明
|
||||
// V1.0 2018.08.08 J.C 正式发布
|
||||
//
|
||||
// 公司名称:多场低温科技有限公司
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifndef __BSP_RES_H__
|
||||
#define __BSP_RES_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// 串联电阻参数选择,主要用于bsp_KeyState()函数的入口参数
|
||||
typedef enum
|
||||
{
|
||||
RES_0 = 7,
|
||||
RES_10,
|
||||
RES_61,
|
||||
RES_100,
|
||||
RES_110,
|
||||
RES_151,
|
||||
RES_202,
|
||||
RES_212
|
||||
}RES_E;
|
||||
|
||||
// 供外面调用的函数声明
|
||||
void bsp_InitRes(void);
|
||||
void bsp_SelectRes(uint8_t _res);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-------------------------------- End of file ---------------------------------
|
||||
50
User/bsp/inc/bsp_step_moto.h
Normal file
50
User/bsp/inc/bsp_step_moto.h
Normal file
@@ -0,0 +1,50 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 模块名称:步进电机脉冲驱动模块
|
||||
// 文件名称:bsp_step_moto
|
||||
// 版本名称:V1.0
|
||||
// 文件说明:头文件
|
||||
// 日期时间:2018年8月23日20点37分
|
||||
// 文件作者:Jackie Chan
|
||||
// 修改记录:
|
||||
// 版本号 日期 作者 说明
|
||||
// V1.0 2018.08.23 J.C 正式发布
|
||||
//
|
||||
// 公司名称:多场低温科技有限公司
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifndef _BSP_STEMP_MOTO_H
|
||||
#define _BSP_STEMP_MOTO_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t Dir; /* 0 表示正转 1 表示反转 */
|
||||
uint32_t StepFreq; /* 步进频率 */
|
||||
uint32_t StepCount; /* 剩余步数 */
|
||||
uint32_t AllStep; /* 一次转动命令所要走的脉冲总数 */
|
||||
uint32_t CurrentStep; /* 已经走过的步数 */
|
||||
uint32_t DispStep; /* 显示走过的步数,零点搜索时候不计数 */
|
||||
uint8_t Running; /* 1表示正在旋转 0 表示停机 */
|
||||
uint8_t Pos; /* 线圈通电的相序,0-7 */
|
||||
int64_t pv_pulse; // 当前的脉冲值
|
||||
int64_t sv_pulse; // 电脑端的设定脉冲值
|
||||
int64_t prev_pv_pulse;// 上一次脉冲值,用于检测过零点
|
||||
} MOTO_T;
|
||||
|
||||
extern MOTO_T g_tMoto;
|
||||
|
||||
void bsp_InitStepMoto(void);
|
||||
void MOTO_Start(uint32_t _speed, uint8_t _dir, int32_t _stpes);
|
||||
void MOTO_ZorePos(void);
|
||||
void MOTO_Stop(void);
|
||||
void MOTO_Pause(void);
|
||||
void MOTO_ShangeSpeed(uint32_t _speed);
|
||||
uint32_t MOTO_RoudToStep(void);
|
||||
|
||||
extern MOTO_T g_tMoto;
|
||||
|
||||
#endif
|
||||
|
||||
/***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
|
||||
29
User/bsp/inc/bsp_tim_pwm.h
Normal file
29
User/bsp/inc/bsp_tim_pwm.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
*
|
||||
* 模块名称 : 利用STM32F4内部TIM输出PWM信号,顺便实现
|
||||
* 文件名称 : bsp_tim_pwm.h
|
||||
* 版 本 : V1.0
|
||||
* 说 明 : 头文件
|
||||
*
|
||||
* Copyright (C), 2012-2013, 安富莱电子 www.armfly.com
|
||||
*
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __BSP_TIM_PWM_H
|
||||
#define __BSP_TIM_PWM_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void bsp_SetTIMOutPWM(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, TIM_TypeDef* TIMx, uint8_t _ucChannel,
|
||||
uint32_t _ulFreq, uint32_t _ulDutyCycle);
|
||||
|
||||
void bsp_SetTIMOutPWM_N(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, TIM_TypeDef* TIMx, uint8_t _ucChannel,
|
||||
uint32_t _ulFreq, uint32_t _ulDutyCycle);
|
||||
|
||||
void bsp_SetTIMforInt(TIM_TypeDef* TIMx, uint32_t _ulFreq, uint8_t _PreemptionPriority, uint8_t _SubPriority);
|
||||
|
||||
#endif
|
||||
|
||||
/***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
|
||||
55
User/bsp/inc/bsp_timer.h
Normal file
55
User/bsp/inc/bsp_timer.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
*
|
||||
* 模块名称 : 定时器模块
|
||||
* 文件名称 : bsp_timer.h
|
||||
* 版 本 : V1.3
|
||||
* 说 明 : 头文件
|
||||
*
|
||||
* Copyright (C), 2015-2016, 安富莱电子 www.armfly.com
|
||||
*
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __BSP_TIMER_H
|
||||
#define __BSP_TIMER_H
|
||||
|
||||
/*
|
||||
在此定义若干个软件定时器全局变量
|
||||
注意,必须增加__IO 即 volatile,因为这个变量在中断和主程序中同时被访问,有可能造成编译器错误优化。
|
||||
*/
|
||||
#define TMR_COUNT 4 /* 软件定时器的个数 (定时器ID范围 0 - 3) */
|
||||
|
||||
/* 定时器结构体,成员变量必须是 volatile, 否则C编译器优化时可能有问题 */
|
||||
typedef enum
|
||||
{
|
||||
TMR_ONCE_MODE = 0, /* 一次工作模式 */
|
||||
TMR_AUTO_MODE = 1 /* 自动定时工作模式 */
|
||||
}TMR_MODE_E;
|
||||
|
||||
/* 定时器结构体,成员变量必须是 volatile, 否则C编译器优化时可能有问题 */
|
||||
typedef struct
|
||||
{
|
||||
volatile uint8_t Mode; /* 计数器模式,1次性 */
|
||||
volatile uint8_t Flag; /* 定时到达标志 */
|
||||
volatile uint32_t Count; /* 计数器 */
|
||||
volatile uint32_t PreLoad; /* 计数器预装值 */
|
||||
}SOFT_TMR;
|
||||
|
||||
/* 提供给其他C文件调用的函数 */
|
||||
void bsp_InitTimer(void);
|
||||
void bsp_DelayMS(uint32_t n);
|
||||
void bsp_DelayUS(uint32_t n);
|
||||
void bsp_StartTimer(uint8_t _id, uint32_t _period);
|
||||
void bsp_StartAutoTimer(uint8_t _id, uint32_t _period);
|
||||
void bsp_StopTimer(uint8_t _id);
|
||||
uint8_t bsp_CheckTimer(uint8_t _id);
|
||||
int32_t bsp_GetRunTime(void);
|
||||
int32_t bsp_CheckRunTime(int32_t _LastTime);
|
||||
|
||||
void bsp_InitHardTimer(void);
|
||||
void bsp_StartHardTimer(uint8_t _CC, uint32_t _uiTimeOut, void * _pCallBack);
|
||||
|
||||
#endif
|
||||
|
||||
/***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
|
||||
47
User/bsp/inc/bsp_usart_dma.h
Normal file
47
User/bsp/inc/bsp_usart_dma.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* @Author: Memory 1619005172@qq.com
|
||||
* @Date: 2026-04-15 18:00:45
|
||||
* @LastEditors: Memory 1619005172@qq.com
|
||||
* @LastEditTime: 2026-04-15 19:25:36
|
||||
* @FilePath: \MDK-ARMd:\Project\MFT\Motor\User\bsp\inc\bsp_usart_dma.h
|
||||
* @Description:
|
||||
*/
|
||||
#ifndef __USARTDMA_H
|
||||
#define __USARTDMA_H
|
||||
|
||||
#include "stm32f10x.h"
|
||||
#include <stdio.h>
|
||||
|
||||
// 串口工作参数宏定义
|
||||
#define DEBUG_USARTx USART1
|
||||
#define DEBUG_USART_CLK RCC_APB2Periph_USART1
|
||||
#define DEBUG_USART_APBxClkCmd RCC_APB2PeriphClockCmd
|
||||
#define DEBUG_USART_BAUDRATE 115200
|
||||
|
||||
// USART GPIO 引脚宏定义
|
||||
#define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOA)
|
||||
#define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd
|
||||
|
||||
#define DEBUG_USART_TX_GPIO_PORT GPIOA
|
||||
#define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_9
|
||||
#define DEBUG_USART_RX_GPIO_PORT GPIOA
|
||||
#define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_10
|
||||
|
||||
#define DEBUG_USART_IRQ USART1_IRQn
|
||||
#define DEBUG_USART_IRQHandler USART1_IRQHandler
|
||||
|
||||
// 串口对应的DMA请求通道
|
||||
#define USART_RX_DMA_CHANNEL DMA1_Channel5
|
||||
// 外设寄存器地址
|
||||
#define USART_DR_ADDRESS (USART1_BASE + 0x04)
|
||||
// 一次发送的数据量
|
||||
#define RECEIVEBUFF_SIZE 64
|
||||
|
||||
void USART_Config(void);
|
||||
void USARTx_DMA_Config(void);
|
||||
void Usart_SendArray(USART_TypeDef *pUSARTx, uint8_t *array, uint16_t num);
|
||||
|
||||
extern uint8_t g_ucRxRcvNewFlag;
|
||||
extern uint8_t g_RxBuf[64];
|
||||
|
||||
#endif /* __USARTDMA_H */
|
||||
93
User/bsp/src/bsp_adc.c
Normal file
93
User/bsp/src/bsp_adc.c
Normal file
@@ -0,0 +1,93 @@
|
||||
#include "bsp_adc.h"
|
||||
// #include "delay.h"
|
||||
|
||||
//初始化ADC
|
||||
//这里我们仅以规则通道为例
|
||||
//我们默认将开启通道0~3
|
||||
void Adc_Init(void)
|
||||
{
|
||||
ADC_InitTypeDef ADC_InitStructure;
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC |RCC_APB2Periph_ADC1, ENABLE ); //使能ADC1通道时钟
|
||||
|
||||
|
||||
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
|
||||
|
||||
//PA1 作为模拟通道输入引脚
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入引脚
|
||||
GPIO_Init(GPIOC, &GPIO_InitStructure);
|
||||
|
||||
ADC_DeInit(ADC1); //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值
|
||||
|
||||
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作模式:ADC1和ADC2工作在独立模式
|
||||
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //模数转换工作在单通道模式
|
||||
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //模数转换工作在单次转换模式
|
||||
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动
|
||||
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐
|
||||
ADC_InitStructure.ADC_NbrOfChannel = 1; //顺序进行规则转换的ADC通道的数目
|
||||
ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器
|
||||
|
||||
|
||||
ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1
|
||||
|
||||
ADC_ResetCalibration(ADC1); //使能复位校准
|
||||
|
||||
while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束
|
||||
|
||||
ADC_StartCalibration(ADC1); //开启AD校准
|
||||
|
||||
while(ADC_GetCalibrationStatus(ADC1)); //等待校准结束
|
||||
|
||||
// ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能
|
||||
|
||||
}
|
||||
//获得ADC值
|
||||
//ch:通道值 0~3 ADC_Channel_1
|
||||
u16 Get_Adc(u8 ch)
|
||||
{
|
||||
//设置指定ADC的规则组通道,一个序列,采样时间
|
||||
ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 ); //ADC1,ADC通道,采样时间为239.5周期
|
||||
|
||||
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能
|
||||
|
||||
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束
|
||||
|
||||
return ADC_GetConversionValue(ADC1); //返回最近一次ADC1规则组的转换结果
|
||||
}
|
||||
|
||||
u16 Get_Adc_Average(u8 ch,u8 times)
|
||||
{
|
||||
u32 temp_val=0;
|
||||
u8 t;
|
||||
for(t=0;t<times;t++)
|
||||
{
|
||||
temp_val+=Get_Adc(ch);
|
||||
// delay_ms(5);
|
||||
}
|
||||
return temp_val/times;
|
||||
}
|
||||
|
||||
u8 get_electric_quantity_percent(void)
|
||||
{
|
||||
u8 electric_quantity_percent = 0;
|
||||
u16 ad_value;
|
||||
|
||||
ad_value = Get_Adc_Average(ADC_Channel_11,10);
|
||||
|
||||
electric_quantity_percent = ((ad_value*3.3/4096.0)-1.846)*100/0.52;
|
||||
|
||||
if(electric_quantity_percent >= 100)
|
||||
{
|
||||
electric_quantity_percent = 100;
|
||||
}
|
||||
else if(electric_quantity_percent <= 0)
|
||||
{
|
||||
electric_quantity_percent = 0;
|
||||
}
|
||||
return electric_quantity_percent;
|
||||
}
|
||||
|
||||
|
||||
|
||||
10
User/bsp/src/bsp_adc.h
Normal file
10
User/bsp/src/bsp_adc.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef __BSP_ADC_H
|
||||
#define __BSP_ADC_H
|
||||
//#include "sys.h"
|
||||
|
||||
void Adc_Init(void);
|
||||
u16 Get_Adc(u8 ch);
|
||||
u16 Get_Adc_Average(u8 ch,u8 times);
|
||||
u8 get_electric_quantity_percent(void);
|
||||
|
||||
#endif
|
||||
189
User/bsp/src/bsp_beep.c
Normal file
189
User/bsp/src/bsp_beep.c
Normal file
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
*
|
||||
* 模块名称 : 蜂鸣器驱动模块
|
||||
* 文件名称 : bsp_beep.c
|
||||
* 版 本 : V1.1
|
||||
* 说 明 : 驱动蜂鸣器.
|
||||
*
|
||||
* 修改记录 :
|
||||
* 版本号 日期 作者 说明
|
||||
* V1.0 2014-10-20 armfly 正式发布
|
||||
* V1.1 2015-08-30 armfly 增加修改蜂鸣器频率的功能 BEEP_Start() 函数添加频率形参
|
||||
*
|
||||
* Copyright (C), 2015-2016, 安富莱电子 www.armfly.com
|
||||
*
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#include "bsp.h"
|
||||
|
||||
#define BEEP_HAVE_POWER /* 定义此行表示有源蜂鸣器,直接通过GPIO驱动, 无需PWM */
|
||||
|
||||
#ifdef BEEP_HAVE_POWER /* 有源蜂鸣器 */
|
||||
|
||||
/* PA8 */
|
||||
#define GPIO_RCC_BEEP RCC_APB2Periph_GPIOB
|
||||
#define GPIO_PORT_BEEP GPIOB
|
||||
#define GPIO_PIN_BEEP GPIO_Pin_8
|
||||
|
||||
#define BEEP_ENABLE() GPIO_PORT_BEEP->BSRR = GPIO_PIN_BEEP /* 使能蜂鸣器鸣叫 */
|
||||
#define BEEP_DISABLE() GPIO_PORT_BEEP->BRR = GPIO_PIN_BEEP /* 禁止蜂鸣器鸣叫 */
|
||||
#else /* 无源蜂鸣器 */
|
||||
/* PA8/TIM1_CH1 ---> TIM1_CH1 */
|
||||
|
||||
/* 1500表示频率1.5KHz,5000表示50.00%的占空比 */
|
||||
#define BEEP_ENABLE() bsp_SetTIMOutPWM(GPIOA, GPIO_Pin_8, TIM1, 1, g_tBeep.uiFreq, 5000);
|
||||
|
||||
/* 禁止蜂鸣器鸣叫 */
|
||||
#define BEEP_DISABLE() bsp_SetTIMOutPWM(GPIOA, GPIO_Pin_8, TIM1, 1, 1500, 0);
|
||||
#endif
|
||||
|
||||
static BEEP_T g_tBeep; /* 定义蜂鸣器全局结构体变量 */
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: BEEP_InitHard
|
||||
* 功能说明: 初始化蜂鸣器硬件
|
||||
* 形 参:无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void BEEP_InitHard(void)
|
||||
{
|
||||
#ifdef BEEP_HAVE_POWER /* 有源蜂鸣器 */
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
/* 打开GPIO的时钟 */
|
||||
RCC_APB2PeriphClockCmd(GPIO_RCC_BEEP, ENABLE);
|
||||
|
||||
BEEP_DISABLE();
|
||||
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; /* 推挽输出模式 */
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_BEEP;
|
||||
GPIO_Init(GPIO_PORT_BEEP, &GPIO_InitStructure);
|
||||
#else
|
||||
; /* 无源蜂鸣器 */
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: BEEP_Start
|
||||
* 功能说明: 启动蜂鸣音。
|
||||
* 形 参:_uiFreq : 频率 (Hz)
|
||||
* _usBeepTime : 蜂鸣时间,单位10ms; 0 表示不鸣叫
|
||||
* _usStopTime : 停止时间,单位10ms; 0 表示持续鸣叫
|
||||
* _usCycle : 鸣叫次数, 0 表示持续鸣叫
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void BEEP_Start(uint32_t _uiFreq, uint16_t _usBeepTime, uint16_t _usStopTime, uint16_t _usCycle)
|
||||
{
|
||||
if (_usBeepTime == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
g_tBeep.uiFreq = _uiFreq;
|
||||
g_tBeep.usBeepTime = _usBeepTime;
|
||||
g_tBeep.usStopTime = _usStopTime;
|
||||
g_tBeep.usCycle = _usCycle;
|
||||
g_tBeep.usCount = 0;
|
||||
g_tBeep.usCycleCount = 0;
|
||||
g_tBeep.ucState = 0;
|
||||
g_tBeep.ucEnalbe = 1; /* 设置完全局参数后再使能发声标志 */
|
||||
|
||||
BEEP_ENABLE(); /* 开始发声 */
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: BEEP_Stop
|
||||
* 功能说明: 停止蜂鸣音。
|
||||
* 形 参:无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void BEEP_Stop(void)
|
||||
{
|
||||
g_tBeep.ucEnalbe = 0;
|
||||
|
||||
BEEP_DISABLE(); /* 必须在清控制标志后再停止发声,避免停止后在中断中又开启 */
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: BEEP_KeyTone
|
||||
* 功能说明: 发送按键音, 固定 1.5KHz
|
||||
* 形 参:无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void BEEP_KeyTone(void)
|
||||
{
|
||||
BEEP_Start(4300, 4, 1, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: BEEP_Pro
|
||||
* 功能说明: 每隔10ms调用1次该函数,用于控制蜂鸣器发声。该函数在 bsp_timer.c 中被调用。
|
||||
* 形 参:无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void BEEP_Pro(void)
|
||||
{
|
||||
if ((g_tBeep.ucEnalbe == 0) || (g_tBeep.usStopTime == 0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_tBeep.ucState == 0)
|
||||
{
|
||||
if (g_tBeep.usStopTime > 0) /* 间断发声 */
|
||||
{
|
||||
if (++g_tBeep.usCount >= g_tBeep.usBeepTime)
|
||||
{
|
||||
BEEP_DISABLE(); /* 停止发声 */
|
||||
g_tBeep.usCount = 0;
|
||||
g_tBeep.ucState = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
; /* 不做任何处理,连续发声 */
|
||||
}
|
||||
}
|
||||
else if (g_tBeep.ucState == 1)
|
||||
{
|
||||
if (++g_tBeep.usCount >= g_tBeep.usStopTime)
|
||||
{
|
||||
/* 连续发声时,直到调用stop停止为止 */
|
||||
if (g_tBeep.usCycle > 0)
|
||||
{
|
||||
if (++g_tBeep.usCycleCount >= g_tBeep.usCycle)
|
||||
{
|
||||
/* 循环次数到,停止发声 */
|
||||
g_tBeep.ucEnalbe = 0;
|
||||
}
|
||||
|
||||
if (g_tBeep.ucEnalbe == 0)
|
||||
{
|
||||
g_tBeep.usStopTime = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
g_tBeep.usCount = 0;
|
||||
g_tBeep.ucState = 0;
|
||||
|
||||
BEEP_ENABLE(); /* 开始发声 */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
|
||||
454
User/bsp/src/bsp_digital_tube.c
Normal file
454
User/bsp/src/bsp_digital_tube.c
Normal file
@@ -0,0 +1,454 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 模块名称:数码管驱动模块
|
||||
// 文件名称:bsp_digital_tube
|
||||
// 版本名称:V1.0
|
||||
// 文件说明:8个0.2寸共阴数码管轮流刷新控制点亮。
|
||||
// 日期时间:2018年8月15日16点42分
|
||||
// 文件作者:Jackie Chan
|
||||
// 修改记录:
|
||||
// 版本号 日期 作者 说明
|
||||
// V1.0 2018.08.15 J.C 正式发布
|
||||
//
|
||||
// 公司名称:多场低温科技有限公司
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#include "bsp.h"
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
|
||||
// 数码管控制引脚对应的RCC时钟
|
||||
#define RCC_ALL_TUBE (RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD)
|
||||
// 数码管的位选,高电平有效
|
||||
#define GPIO_PORT_A GPIOD
|
||||
#define GPIO_PIN_A GPIO_Pin_0
|
||||
#define GPIO_PORT_B GPIOD
|
||||
#define GPIO_PIN_B GPIO_Pin_1
|
||||
#define GPIO_PORT_C GPIOD
|
||||
#define GPIO_PIN_C GPIO_Pin_2
|
||||
#define GPIO_PORT_D GPIOD
|
||||
#define GPIO_PIN_D GPIO_Pin_3
|
||||
#define GPIO_PORT_E GPIOD
|
||||
#define GPIO_PIN_E GPIO_Pin_4
|
||||
#define GPIO_PORT_F GPIOD
|
||||
#define GPIO_PIN_F GPIO_Pin_5
|
||||
#define GPIO_PORT_G GPIOD
|
||||
#define GPIO_PIN_G GPIO_Pin_6
|
||||
#define GPIO_PORT_H GPIOD
|
||||
#define GPIO_PIN_H GPIO_Pin_7
|
||||
// 数码管的段选,高电平有效
|
||||
#define GPIO_PORT_DS1 GPIOC
|
||||
#define GPIO_PIN_DS1 GPIO_Pin_9
|
||||
#define GPIO_PORT_DS2 GPIOC
|
||||
#define GPIO_PIN_DS2 GPIO_Pin_8
|
||||
#define GPIO_PORT_DS3 GPIOC
|
||||
#define GPIO_PIN_DS3 GPIO_Pin_10
|
||||
#define GPIO_PORT_DS4 GPIOC
|
||||
#define GPIO_PIN_DS4 GPIO_Pin_6
|
||||
#define GPIO_PORT_DS5 GPIOD
|
||||
#define GPIO_PIN_DS5 GPIO_Pin_11
|
||||
#define GPIO_PORT_DS6 GPIOD
|
||||
#define GPIO_PIN_DS6 GPIO_Pin_10
|
||||
#define GPIO_PORT_DS7 GPIOD
|
||||
#define GPIO_PIN_DS7 GPIO_Pin_9
|
||||
#define GPIO_PORT_DS8 GPIOD
|
||||
#define GPIO_PIN_DS8 GPIO_Pin_8
|
||||
|
||||
// 关闭所有段选
|
||||
#define CLOSE_ALL_TUBE_COM \
|
||||
do \
|
||||
{ \
|
||||
GPIO_PORT_DS1->BRR = GPIO_PIN_DS1; \
|
||||
GPIO_PORT_DS2->BRR = GPIO_PIN_DS2; \
|
||||
GPIO_PORT_DS3->BRR = GPIO_PIN_DS3; \
|
||||
GPIO_PORT_DS4->BRR = GPIO_PIN_DS4; \
|
||||
GPIO_PORT_DS5->BRR = GPIO_PIN_DS5; \
|
||||
GPIO_PORT_DS6->BRR = GPIO_PIN_DS6; \
|
||||
GPIO_PORT_DS7->BRR = GPIO_PIN_DS7; \
|
||||
GPIO_PORT_DS8->BRR = GPIO_PIN_DS8; \
|
||||
} while (0)
|
||||
// 关闭所有位选
|
||||
#define CLOSE_ALL_TUBE_SEG \
|
||||
do \
|
||||
{ \
|
||||
GPIO_PORT_A->BRR = GPIO_PIN_A; \
|
||||
GPIO_PORT_B->BRR = GPIO_PIN_B; \
|
||||
GPIO_PORT_C->BRR = GPIO_PIN_C; \
|
||||
GPIO_PORT_D->BRR = GPIO_PIN_D; \
|
||||
GPIO_PORT_E->BRR = GPIO_PIN_E; \
|
||||
GPIO_PORT_F->BRR = GPIO_PIN_F; \
|
||||
GPIO_PORT_G->BRR = GPIO_PIN_G; \
|
||||
GPIO_PORT_H->BRR = GPIO_PIN_H; \
|
||||
} while (0)
|
||||
|
||||
// 数码管共阴或者共阳选择,用于正确输出位选电平
|
||||
#define SEG_A 0X01
|
||||
#define SEG_B 0X01
|
||||
#define SEG_C 0X01
|
||||
#define SEG_D 0X01
|
||||
#define SEG_E 0X01
|
||||
#define SEG_F 0X01
|
||||
#define SEG_G 0X01
|
||||
#define SEG_H 0X01
|
||||
#define SEG_0 0X00 // 数码管的该段<不点亮>
|
||||
|
||||
const uint8_t g_tube_table[12][7] = {
|
||||
{SEG_A, SEG_B, SEG_C, SEG_D, SEG_E, SEG_F, SEG_0}, // NO_0
|
||||
{SEG_0, SEG_B, SEG_C, SEG_0, SEG_0, SEG_0, SEG_0}, // NO_1
|
||||
{SEG_A, SEG_B, SEG_0, SEG_D, SEG_E, SEG_0, SEG_G}, // NO_2
|
||||
{SEG_A, SEG_B, SEG_C, SEG_D, SEG_0, SEG_0, SEG_G}, // NO_3
|
||||
{SEG_0, SEG_B, SEG_C, SEG_0, SEG_0, SEG_F, SEG_G}, // NO_4
|
||||
{SEG_A, SEG_0, SEG_C, SEG_D, SEG_0, SEG_F, SEG_G}, // NO_5
|
||||
{SEG_A, SEG_0, SEG_C, SEG_D, SEG_E, SEG_F, SEG_G}, // NO_6
|
||||
{SEG_A, SEG_B, SEG_C, SEG_0, SEG_0, SEG_0, SEG_0}, // NO_7
|
||||
{SEG_A, SEG_B, SEG_C, SEG_D, SEG_E, SEG_F, SEG_G}, // NO_8
|
||||
{SEG_A, SEG_B, SEG_C, SEG_D, SEG_0, SEG_F, SEG_G}, // NO_9
|
||||
{SEG_0, SEG_0, SEG_0, SEG_0, SEG_0, SEG_0, SEG_G}, // NO__
|
||||
{SEG_0, SEG_0, SEG_0, SEG_0, SEG_0, SEG_0, SEG_0}, // NO_NULL
|
||||
};
|
||||
|
||||
// 全局变量声明
|
||||
DIGITIAL_TUBE_T g_tTube;
|
||||
extern MOTO_T g_tMoto;
|
||||
|
||||
// 该文件中的所有函数声明
|
||||
void bsp_InitDigitalTube(void);
|
||||
void bsp_DigitalTubeMainLoop(void);
|
||||
void bsp_TubeTest(uint8_t _com, uint8_t _seg);
|
||||
void bsp_InitTubeVar(void);
|
||||
void bsp_UpdateDisplayBuf(void);
|
||||
void bsp_ToogleWorkMode(void);
|
||||
void bsp_ToogleStateMode(void);
|
||||
void bsp_Pulse2Buf(void);
|
||||
void bsp_Angle2Buf(void);
|
||||
static void bsp_ReadDatFromEEPROM(void);
|
||||
|
||||
void bsp_InitTubeVar(void)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
g_tTube.buf[i] = NO_NULL;
|
||||
}
|
||||
g_tTube.disp_mode = MODE_PULSE;
|
||||
g_tTube.cnt = 0;
|
||||
g_tTube.state = IDLE;
|
||||
// g_tTube.state = WORK;
|
||||
g_tTube.dir = DIR_CW;
|
||||
g_tTube.pulse = 0;
|
||||
g_tTube.tim_pulse_cnt = 0;
|
||||
g_tTube.angle = 0;
|
||||
}
|
||||
|
||||
void bsp_TubeTest(uint8_t _com, uint8_t _seg)
|
||||
{
|
||||
if (_seg == ' ')
|
||||
_seg = NO_NULL;
|
||||
if (_seg >= 12)
|
||||
return;
|
||||
|
||||
CLOSE_ALL_TUBE_COM;
|
||||
CLOSE_ALL_TUBE_SEG;
|
||||
|
||||
if (g_tube_table[_seg][0])
|
||||
{
|
||||
GPIO_PORT_A->BSRR = GPIO_PIN_A;
|
||||
};
|
||||
if (g_tube_table[_seg][1])
|
||||
{
|
||||
GPIO_PORT_B->BSRR = GPIO_PIN_B;
|
||||
};
|
||||
if (g_tube_table[_seg][2])
|
||||
{
|
||||
GPIO_PORT_C->BSRR = GPIO_PIN_C;
|
||||
};
|
||||
if (g_tube_table[_seg][3])
|
||||
{
|
||||
GPIO_PORT_D->BSRR = GPIO_PIN_D;
|
||||
};
|
||||
if (g_tube_table[_seg][4])
|
||||
{
|
||||
GPIO_PORT_E->BSRR = GPIO_PIN_E;
|
||||
};
|
||||
if (g_tube_table[_seg][5])
|
||||
{
|
||||
GPIO_PORT_F->BSRR = GPIO_PIN_F;
|
||||
};
|
||||
if (g_tube_table[_seg][6])
|
||||
{
|
||||
GPIO_PORT_G->BSRR = GPIO_PIN_G;
|
||||
};
|
||||
if ((_com == 5) && (g_tTube.disp_mode == MODE_ANGLE))
|
||||
{
|
||||
GPIO_PORT_H->BSRR = GPIO_PIN_H;
|
||||
}
|
||||
|
||||
switch (_com)
|
||||
{
|
||||
case 0:
|
||||
GPIO_PORT_DS1->BSRR = GPIO_PIN_DS1;
|
||||
break;
|
||||
case 1:
|
||||
GPIO_PORT_DS2->BSRR = GPIO_PIN_DS2;
|
||||
break;
|
||||
case 2:
|
||||
GPIO_PORT_DS3->BSRR = GPIO_PIN_DS3;
|
||||
break;
|
||||
case 3:
|
||||
GPIO_PORT_DS4->BSRR = GPIO_PIN_DS4;
|
||||
break;
|
||||
case 4:
|
||||
GPIO_PORT_DS5->BSRR = GPIO_PIN_DS5;
|
||||
break;
|
||||
case 5:
|
||||
GPIO_PORT_DS6->BSRR = GPIO_PIN_DS6;
|
||||
break;
|
||||
case 6:
|
||||
GPIO_PORT_DS7->BSRR = GPIO_PIN_DS7;
|
||||
break;
|
||||
case 7:
|
||||
GPIO_PORT_DS8->BSRR = GPIO_PIN_DS8;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
void bsp_ToogleDispMode(void)
|
||||
{
|
||||
uint8_t buf[5]; // PULSE: 55AA00FF; ANGLE: FF00AA55
|
||||
|
||||
switch (g_tTube.disp_mode)
|
||||
{
|
||||
case MODE_PULSE:
|
||||
g_tTube.disp_mode = MODE_ANGLE;
|
||||
break;
|
||||
case MODE_ANGLE:
|
||||
g_tTube.disp_mode = MODE_PULSE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (g_tTube.disp_mode == MODE_ANGLE)
|
||||
{
|
||||
buf[0] = 0xFF;
|
||||
buf[1] = 0x00;
|
||||
buf[2] = 0xAA;
|
||||
buf[3] = 0x55;
|
||||
ee_WriteBytes(buf, 0, 4);
|
||||
}
|
||||
else if (g_tTube.disp_mode == MODE_PULSE)
|
||||
{
|
||||
buf[0] = 0x55;
|
||||
buf[1] = 0xAA;
|
||||
buf[2] = 0x00;
|
||||
buf[3] = 0xFF;
|
||||
ee_WriteBytes(buf, 0, 4);
|
||||
}
|
||||
|
||||
bsp_UpdateDisplayBuf();
|
||||
}
|
||||
void bsp_ToogleStateMode(void)
|
||||
{
|
||||
switch (g_tTube.state)
|
||||
{
|
||||
case IDLE:
|
||||
g_tTube.state = WORK;
|
||||
break;
|
||||
case WORK:
|
||||
g_tTube.state = IDLE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
bsp_UpdateDisplayBuf();
|
||||
}
|
||||
|
||||
void bsp_UpdateDisplayBuf(void)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
|
||||
// 开机或执行了搜索命令但未找到零点时的数码管显示状态
|
||||
if ((g_tTube.state == IDLE) || (g_tTube.state == SEARCH))
|
||||
{
|
||||
if (g_tTube.disp_mode == MODE_PULSE) // 数码管显示[--------]
|
||||
{
|
||||
memset(g_tTube.buf, NO__, 8);
|
||||
}
|
||||
else if (g_tTube.disp_mode == MODE_ANGLE) // 数码管显示[ -.--]
|
||||
{
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
g_tTube.buf[i] = NO_NULL;
|
||||
}
|
||||
g_tTube.buf[5] = NO__;
|
||||
g_tTube.buf[6] = NO__;
|
||||
g_tTube.buf[7] = NO__;
|
||||
}
|
||||
}
|
||||
else if (g_tTube.state == WORK) // 已经找到零点后数码管的显示状态
|
||||
{
|
||||
bsp_Angle2Buf(); // 数码管显示,例如[-1234567]
|
||||
}
|
||||
}
|
||||
void bsp_Pulse2Buf(void)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
|
||||
memset(g_tTube.buf, 0, 8);
|
||||
snprintf(g_tTube.buf, 9, "%8d", g_tTube.pulse);
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
if (g_tTube.buf[i] == ' ')
|
||||
{
|
||||
g_tTube.buf[i] = NO_NULL;
|
||||
}
|
||||
else if (g_tTube.buf[i] == '-')
|
||||
{
|
||||
g_tTube.buf[i] = NO__;
|
||||
}
|
||||
else if (isdigit(g_tTube.buf[i]))
|
||||
{
|
||||
g_tTube.buf[i] = g_tTube.buf[i] - '0';
|
||||
}
|
||||
}
|
||||
}
|
||||
void bsp_Angle2Buf(void)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
float angle = (((g_tTube.pulse % STEP_PER_LAP) + STEP_PER_LAP) % STEP_PER_LAP) * 360.0f / (STEP_PER_LAP / 100.0f);
|
||||
// printf("angle = %f\r\n", angle);
|
||||
if (angle < 0)
|
||||
{
|
||||
angle -= 0.5f; // 负数向下取整
|
||||
angle += 360.0f; // 转换成整角度
|
||||
}
|
||||
else
|
||||
angle += 0.5f; // 正数向上取整
|
||||
|
||||
// printf("angle = %f\r\n", angle);
|
||||
|
||||
memset(g_tTube.buf, 0, 8);
|
||||
g_tTube.angle = angle;
|
||||
snprintf(g_tTube.buf, 9, "%8d", g_tTube.angle);
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
if (g_tTube.buf[i] == ' ')
|
||||
{
|
||||
g_tTube.buf[i] = NO_NULL;
|
||||
if (i >= 5)
|
||||
{
|
||||
g_tTube.buf[i] = NO_0;
|
||||
}
|
||||
}
|
||||
else if (g_tTube.buf[i] == '-')
|
||||
{
|
||||
if (i >= 5)
|
||||
{
|
||||
g_tTube.buf[4] = NO__;
|
||||
g_tTube.buf[i] = NO_0;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_tTube.buf[i] = NO__;
|
||||
}
|
||||
}
|
||||
else if (isdigit(g_tTube.buf[i]))
|
||||
{
|
||||
g_tTube.buf[i] = g_tTube.buf[i] - '0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bsp_DigitalTubeMainLoop(void)
|
||||
{
|
||||
static uint8_t i = 0;
|
||||
if (++i >= 50) // 该函数每1ms调用一次,每50ms刷新一次脉冲或角度值
|
||||
{
|
||||
i = 0;
|
||||
if (g_tTube.dir == DIR_CCW)
|
||||
{
|
||||
g_tTube.pulse = g_tMoto.pv_pulse;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_tTube.pulse = g_tMoto.pv_pulse;
|
||||
}
|
||||
bsp_UpdateDisplayBuf();
|
||||
}
|
||||
bsp_TubeTest(g_tTube.cnt, g_tTube.buf[g_tTube.cnt]);
|
||||
if (++g_tTube.cnt >= 8)
|
||||
g_tTube.cnt = 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// 函 数 名: bsp_InitDigitalTube
|
||||
// 功能说明: 配置数码管相关的GPIO, 该函数被 bsp_Init() 调用。
|
||||
// 形 参: 无
|
||||
// 返 回 值: 无
|
||||
//------------------------------------------------------------------------------
|
||||
void bsp_InitDigitalTube(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
// 打开数码管GPIO时钟
|
||||
RCC_APB2PeriphClockCmd(RCC_ALL_TUBE, ENABLE);
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出模式
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_A; // 位 a
|
||||
GPIO_Init(GPIO_PORT_A, &GPIO_InitStructure);
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_B; // 位 b
|
||||
GPIO_Init(GPIO_PORT_B, &GPIO_InitStructure);
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_C; // 位 c
|
||||
GPIO_Init(GPIO_PORT_C, &GPIO_InitStructure);
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_D; // 位 d
|
||||
GPIO_Init(GPIO_PORT_D, &GPIO_InitStructure);
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_E; // 位 e
|
||||
GPIO_Init(GPIO_PORT_E, &GPIO_InitStructure);
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_F; // 位 f
|
||||
GPIO_Init(GPIO_PORT_F, &GPIO_InitStructure);
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_G; // 位 g
|
||||
GPIO_Init(GPIO_PORT_G, &GPIO_InitStructure);
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_H; // 位 h
|
||||
GPIO_Init(GPIO_PORT_H, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_DS1; // 段 1
|
||||
GPIO_Init(GPIO_PORT_DS1, &GPIO_InitStructure);
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_DS2; // 段 2
|
||||
GPIO_Init(GPIO_PORT_DS2, &GPIO_InitStructure);
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_DS3; // 段 3
|
||||
GPIO_Init(GPIO_PORT_DS3, &GPIO_InitStructure);
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_DS4; // 段 4
|
||||
GPIO_Init(GPIO_PORT_DS4, &GPIO_InitStructure);
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_DS5; // 段 5
|
||||
GPIO_Init(GPIO_PORT_DS5, &GPIO_InitStructure);
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_DS6; // 段 6
|
||||
GPIO_Init(GPIO_PORT_DS6, &GPIO_InitStructure);
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_DS7; // 段 7
|
||||
GPIO_Init(GPIO_PORT_DS7, &GPIO_InitStructure);
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_DS8; // 段 8
|
||||
GPIO_Init(GPIO_PORT_DS8, &GPIO_InitStructure);
|
||||
|
||||
bsp_InitTubeVar();
|
||||
bsp_ReadDatFromEEPROM();
|
||||
bsp_UpdateDisplayBuf();
|
||||
}
|
||||
|
||||
static void bsp_ReadDatFromEEPROM(void)
|
||||
{
|
||||
uint8_t buf[5]; // PULSE: 55AA00FF; ANGLE: FF00AA55
|
||||
|
||||
ee_ReadBytes((uint8_t *)buf, 0, 4);
|
||||
if ((buf[0] == 0X55) && (buf[1] == 0XAA) && (buf[2] == 0X00) && (buf[3] == 0XFF))
|
||||
{
|
||||
g_tTube.disp_mode = MODE_PULSE;
|
||||
}
|
||||
else if ((buf[0] == 0XFF) && (buf[1] == 0X00) && (buf[2] == 0XAA) && (buf[3] == 0X55))
|
||||
{
|
||||
g_tTube.disp_mode = MODE_ANGLE;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------- End of file ---------------------------------
|
||||
268
User/bsp/src/bsp_drv8880.c
Normal file
268
User/bsp/src/bsp_drv8880.c
Normal file
@@ -0,0 +1,268 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 模块名称:步进电机芯片DRV8880驱动模块
|
||||
// 文件名称:bsp_drv8880
|
||||
// 版本名称:V1.0
|
||||
// 文件说明:控制步进电机芯片DRV8880
|
||||
// 日期时间:2018年8月17日16点23分
|
||||
// 文件作者:Jackie Chan
|
||||
// 修改记录:
|
||||
// 版本号 日期 作者 说明
|
||||
// V1.0 2018.08.17 J.C 正式发布
|
||||
//
|
||||
// 公司名称:多场低温科技有限公司
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#include "bsp.h"
|
||||
|
||||
// DRV888控制引脚对应的RCC时钟
|
||||
#define RCC_ALL_MOTO (RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | \
|
||||
RCC_APB2Periph_GPIOE | RCC_APB2Periph_GPIOG)
|
||||
|
||||
// DRV8880控制引脚
|
||||
#define GPIO_PORT_STEP GPIOC // 脉冲输入,内部下拉,上升沿触发
|
||||
#define GPIO_PIN_STEP GPIO_Pin_7
|
||||
|
||||
#define GPIO_PORT_DIR GPIOE // 转动方向,内部下拉
|
||||
#define GPIO_PIN_DIR GPIO_Pin_10
|
||||
|
||||
#define GPIO_PORT_ENABLE GPIOE // 器件使能,内部下拉
|
||||
#define GPIO_PIN_ENABLE GPIO_Pin_11
|
||||
|
||||
#define GPIO_PORT_SLEEP GPIOB // 低电平进入睡眠模式,内部下拉
|
||||
#define GPIO_PIN_SLEEP GPIO_Pin_11
|
||||
|
||||
#define GPIO_PORT_ATE GPIOE // 高电平进入自动整定模式,内部下拉
|
||||
#define GPIO_PIN_ATE GPIO_Pin_15
|
||||
|
||||
#define GPIO_PORT_TRQ1 GPIOG // 力矩设置,内部下拉
|
||||
#define GPIO_PIN_TRQ1 GPIO_Pin_1
|
||||
|
||||
#define GPIO_PORT_TRQ0 GPIOG // 力矩设置,内部下拉
|
||||
#define GPIO_PIN_TRQ0 GPIO_Pin_0
|
||||
|
||||
#define GPIO_PORT_M1 GPIOE // 细分,三态输入引脚
|
||||
#define GPIO_PIN_M1 GPIO_Pin_8
|
||||
|
||||
#define GPIO_PORT_M0 GPIOE // 细分,三态输入引脚
|
||||
#define GPIO_PIN_M0 GPIO_Pin_7
|
||||
|
||||
#define GPIO_PORT_DECAY1 GPIOE // 衰减模式设置,自动整定时被忽略
|
||||
#define GPIO_PIN_DECAY1 GPIO_Pin_13
|
||||
|
||||
#define GPIO_PORT_DECAY0 GPIOE // 衰减模式设置,自动整定时被忽略
|
||||
#define GPIO_PIN_DECAY0 GPIO_Pin_12
|
||||
|
||||
#define GPIO_PORT_TOFF GPIOB // Off time设置,三态输入
|
||||
#define GPIO_PIN_TOFF GPIO_Pin_10
|
||||
|
||||
#define GPIO_PORT_FAULT GPIOE // 失效报警输出,开漏输出
|
||||
#define GPIO_PIN_FAULT GPIO_Pin_14
|
||||
|
||||
// 细分相关宏定义
|
||||
#define M1_ENABLE (GPIO_PORT_M1->BSRR = GPIO_PIN_M1)
|
||||
#define M0_ENABLE (GPIO_PORT_M0->BSRR = GPIO_PIN_M0)
|
||||
#define M1_DISABLE (GPIO_PORT_M1->BRR = GPIO_PIN_M1)
|
||||
#define M0_DISABLE (GPIO_PORT_M0->BRR = GPIO_PIN_M0)
|
||||
#define M0_SET_AS_INPUT() \
|
||||
{ \
|
||||
GPIO_PORT_M0->CRL &= 0X0FFFFFFF; \
|
||||
GPIO_PORT_M0->CRL |= 0X40000000; \
|
||||
}
|
||||
#define M0_SET_AS_OUTPUT() \
|
||||
{ \
|
||||
GPIO_PORT_M0->CRL &= 0X0FFFFFFF; \
|
||||
GPIO_PORT_M0->CRL |= 0X30000000; \
|
||||
}
|
||||
|
||||
// DRV8880使能相关宏定义
|
||||
#define DRV8880_ENABLE (GPIO_PORT_ENABLE->BSRR = GPIO_PIN_ENABLE)
|
||||
#define DRV8880_DISABLE (GPIO_PORT_ENABLE->BRR = GPIO_PIN_ENABLE)
|
||||
|
||||
// DRV8880方向控制引脚
|
||||
#define DRV8880_CW (GPIO_PORT_DIR->BRR = GPIO_PIN_DIR) // 样品杆从上往下看,顺时针旋转(+)
|
||||
#define DRV8880_CCW (GPIO_PORT_DIR->BSRR = GPIO_PIN_DIR) // 样品杆从上往下看,逆时针旋转(-)
|
||||
|
||||
extern DIGITIAL_TUBE_T g_tTube;
|
||||
|
||||
// 供外部调用的函数声明
|
||||
void bsp_Init_Drv8880_Hard(void);
|
||||
void bsp_drv8880_enable_config(FunctionalState en);
|
||||
void bsp_drv8880_microstep_config(MICRO_STEPPING_E step);
|
||||
void bsp_drv8880_config_dir(DIR_E dir);
|
||||
// void bsp_drv8880_vref_config(uint16_t vol); // vol:0~3300,代表0~3.3V
|
||||
static void bsp_dev8880_vref_init_hard(uint16_t vol); // vol:0~3300,代表0~3.3V
|
||||
|
||||
void bsp_drv8880_microstep_config(MICRO_STEPPING_E step)
|
||||
{
|
||||
switch (step)
|
||||
{
|
||||
case STEP_FULL: // M1M0: 00
|
||||
M0_SET_AS_OUTPUT();
|
||||
M1_DISABLE;
|
||||
M0_DISABLE;
|
||||
break;
|
||||
case STEP_1_2_NC: // M1M0: 01
|
||||
M0_SET_AS_OUTPUT();
|
||||
M1_DISABLE;
|
||||
M0_ENABLE;
|
||||
break;
|
||||
case STEP_1_2: // M1M0: 10
|
||||
M0_SET_AS_OUTPUT();
|
||||
M1_ENABLE;
|
||||
M0_DISABLE;
|
||||
break;
|
||||
case STEP_1_4: // M1M0: 11
|
||||
M0_SET_AS_OUTPUT();
|
||||
M1_ENABLE;
|
||||
M0_ENABLE;
|
||||
break;
|
||||
case STEP_1_8: // M1M0: 0Z
|
||||
M0_SET_AS_INPUT();
|
||||
M1_DISABLE;
|
||||
break;
|
||||
case STEP_1_16: // M1M0: 1Z
|
||||
M0_SET_AS_INPUT();
|
||||
M1_ENABLE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
void bsp_drv8880_config_dir(DIR_E dir)
|
||||
{
|
||||
switch (dir)
|
||||
{
|
||||
case DIR_CW:
|
||||
DRV8880_CW;
|
||||
g_tTube.dir = DIR_CW;
|
||||
break;
|
||||
case DIR_CCW:
|
||||
DRV8880_CCW;
|
||||
g_tTube.dir = DIR_CCW;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
void bsp_drv8880_enable_config(FunctionalState en)
|
||||
{
|
||||
if (en == DISABLE)
|
||||
{
|
||||
DRV8880_DISABLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
DRV8880_ENABLE;
|
||||
}
|
||||
}
|
||||
|
||||
// vol:0~3300,代表0~3.3V
|
||||
static void bsp_dev8880_vref_init_hard(uint16_t vol)
|
||||
{
|
||||
float temp = vol;
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
DAC_InitTypeDef DAC_InitType;
|
||||
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 使能PORTA通道时钟
|
||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE); // 使能DAC通道时钟
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; // 端口配置
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; // 模拟输入
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||||
GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||||
GPIO_SetBits(GPIOA, GPIO_Pin_4); // PA.4 输出高
|
||||
|
||||
DAC_InitType.DAC_Trigger = DAC_Trigger_None; // 不使用触发功能 TEN1=0
|
||||
DAC_InitType.DAC_WaveGeneration = DAC_WaveGeneration_None; // 不使用波形发生
|
||||
DAC_InitType.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0; // 屏蔽、幅值设置
|
||||
DAC_InitType.DAC_OutputBuffer = DAC_OutputBuffer_Disable; // DAC1输出缓存关闭 BOFF1=1
|
||||
DAC_Init(DAC_Channel_1, &DAC_InitType); // 初始化DAC通道1
|
||||
|
||||
DAC_Cmd(DAC_Channel_1, ENABLE); // 使能DAC1
|
||||
|
||||
DAC_SetChannel1Data(DAC_Align_12b_R, 0); // 12位右对齐数据格式设置DAC值
|
||||
|
||||
temp /= 1000;
|
||||
temp = temp * 4096 / 3.3;
|
||||
DAC_SetChannel1Data(DAC_Align_12b_R, temp); // 12位右对齐数据格式设置DAC值
|
||||
}
|
||||
|
||||
void bsp_Init_Drv8880_Hard(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
RCC_APB2PeriphClockCmd(RCC_ALL_MOTO, ENABLE);
|
||||
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
|
||||
|
||||
// 配置自动整定引脚为高电平,设置为自动整定模式
|
||||
GPIO_PORT_ATE->BSRR = GPIO_PIN_ATE;
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_ATE;
|
||||
GPIO_Init(GPIO_PORT_ATE, &GPIO_InitStructure);
|
||||
|
||||
// 配置脉冲输入引脚,设置为默认低电平
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_STEP;
|
||||
GPIO_Init(GPIO_PORT_STEP, &GPIO_InitStructure);
|
||||
|
||||
// 配置方向引脚,设置默认为低电平
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_DIR;
|
||||
GPIO_Init(GPIO_PORT_DIR, &GPIO_InitStructure);
|
||||
|
||||
// 配置使能引脚,设置默认为低电平,不使能
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_ENABLE;
|
||||
GPIO_Init(GPIO_PORT_ENABLE, &GPIO_InitStructure);
|
||||
|
||||
// 配置睡眠引脚,设置默认为低电平,处于睡眠状态
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_SLEEP;
|
||||
GPIO_Init(GPIO_PORT_SLEEP, &GPIO_InitStructure);
|
||||
|
||||
// 配置细分引脚,设置默认为低电平,不细分
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_M1;
|
||||
GPIO_Init(GPIO_PORT_M1, &GPIO_InitStructure);
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_M0;
|
||||
GPIO_Init(GPIO_PORT_M0, &GPIO_InitStructure);
|
||||
|
||||
// 配置力矩引脚,设置默认为低电平,100%力矩
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_TRQ1;
|
||||
GPIO_Init(GPIO_PORT_TRQ1, &GPIO_InitStructure);
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_TRQ0;
|
||||
GPIO_Init(GPIO_PORT_TRQ0, &GPIO_InitStructure);
|
||||
|
||||
// 设置衰减模式,设置默认为低电平,为slow decay模式
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_DECAY1;
|
||||
GPIO_Init(GPIO_PORT_DECAY1, &GPIO_InitStructure);
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_DECAY0;
|
||||
GPIO_Init(GPIO_PORT_DECAY0, &GPIO_InitStructure);
|
||||
|
||||
// 设置fixed-off-time,设置默认为低电平,为20us
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_TOFF;
|
||||
GPIO_Init(GPIO_PORT_TOFF, &GPIO_InitStructure);
|
||||
|
||||
// 设置报警输出引脚,设置为输入浮空模式
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_FAULT;
|
||||
GPIO_Init(GPIO_PORT_FAULT, &GPIO_InitStructure);
|
||||
|
||||
// 设置细分
|
||||
bsp_drv8880_microstep_config(STEP_1_16);
|
||||
|
||||
// 方向设置
|
||||
bsp_drv8880_config_dir(DIR_CCW);
|
||||
|
||||
// DA输出,步进电机电流设置 0.495V
|
||||
|
||||
// 设置DA输出的电压为0.495V
|
||||
bsp_dev8880_vref_init_hard(1500);
|
||||
|
||||
// 退出睡眠模式
|
||||
GPIO_PORT_SLEEP->BSRR = GPIO_PIN_SLEEP;
|
||||
|
||||
// 暂时不使能,等待零点所搜命令
|
||||
// bsp_drv8880_enable_config(DISABLE);
|
||||
bsp_drv8880_enable_config(ENABLE);
|
||||
}
|
||||
|
||||
//-------------------------------- End of file ---------------------------------
|
||||
236
User/bsp/src/bsp_eeprom_24xx.c
Normal file
236
User/bsp/src/bsp_eeprom_24xx.c
Normal file
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
*
|
||||
* 模块名称 : 串行EEPROM 24xx驱动模块
|
||||
* 文件名称 : bsp_eeprom_24xx.c
|
||||
* 版 本 : V1.0
|
||||
* 说 明 : 实现24xx系列EEPROM的读写操作。写操作采用页写模式提高写入效率。
|
||||
*
|
||||
* 修改记录 :
|
||||
* 版本号 日期 作者 说明
|
||||
* V1.0 2013-02-01 armfly 正式发布
|
||||
*
|
||||
* Copyright (C), 2013-2014, 安富莱电子 www.armfly.com
|
||||
*
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
应用说明:访问串行EEPROM前,请先调用一次 bsp_InitI2C()函数配置好I2C相关的GPIO.
|
||||
*/
|
||||
|
||||
#include "bsp.h"
|
||||
#include "demo_i2c_eeprom.h"
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: ee_CheckOk
|
||||
* 功能说明: 判断串行EERPOM是否正常
|
||||
* 形 参: 无
|
||||
* 返 回 值: 1 表示正常, 0 表示不正常
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
uint8_t ee_CheckOk(void)
|
||||
{
|
||||
if (i2c_CheckDevice(EE_DEV_ADDR) == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 失败后,切记发送I2C总线停止信号 */
|
||||
i2c_Stop();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: ee_ReadBytes
|
||||
* 功能说明: 从串行EEPROM指定地址处开始读取若干数据
|
||||
* 形 参: _usAddress : 起始地址
|
||||
* _usSize : 数据长度,单位为字节
|
||||
* _pReadBuf : 存放读到的数据的缓冲区指针
|
||||
* 返 回 值: 0 表示失败,1表示成功
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
uint8_t ee_ReadBytes(uint8_t *_pReadBuf, uint16_t _usAddress, uint16_t _usSize)
|
||||
{
|
||||
uint16_t i;
|
||||
|
||||
/* 采用串行EEPROM随即读取指令序列,连续读取若干字节 */
|
||||
|
||||
/* 第1步:发起I2C总线启动信号 */
|
||||
i2c_Start();
|
||||
|
||||
/* 第2步:发起控制字节,高7bit是地址,bit0是读写控制位,0表示写,1表示读 */
|
||||
i2c_SendByte(EE_DEV_ADDR | I2C_WR); /* 此处是写指令 */
|
||||
|
||||
/* 第3步:发送ACK */
|
||||
if (i2c_WaitAck() != 0)
|
||||
{
|
||||
goto cmd_fail; /* EEPROM器件无应答 */
|
||||
}
|
||||
|
||||
/* 第4步:发送字节地址,24C02只有256字节,因此1个字节就够了,如果是24C04以上,那么此处需要连发多个地址 */
|
||||
if (EE_ADDR_BYTES == 1)
|
||||
{
|
||||
i2c_SendByte((uint8_t)_usAddress);
|
||||
if (i2c_WaitAck() != 0)
|
||||
{
|
||||
goto cmd_fail; /* EEPROM器件无应答 */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
i2c_SendByte(_usAddress >> 8);
|
||||
if (i2c_WaitAck() != 0)
|
||||
{
|
||||
goto cmd_fail; /* EEPROM器件无应答 */
|
||||
}
|
||||
|
||||
i2c_SendByte(_usAddress);
|
||||
if (i2c_WaitAck() != 0)
|
||||
{
|
||||
goto cmd_fail; /* EEPROM器件无应答 */
|
||||
}
|
||||
}
|
||||
|
||||
/* 第6步:重新启动I2C总线。下面开始读取数据 */
|
||||
i2c_Start();
|
||||
|
||||
/* 第7步:发起控制字节,高7bit是地址,bit0是读写控制位,0表示写,1表示读 */
|
||||
i2c_SendByte(EE_DEV_ADDR | I2C_RD); /* 此处是读指令 */
|
||||
|
||||
/* 第8步:发送ACK */
|
||||
if (i2c_WaitAck() != 0)
|
||||
{
|
||||
goto cmd_fail; /* EEPROM器件无应答 */
|
||||
}
|
||||
|
||||
/* 第9步:循环读取数据 */
|
||||
for (i = 0; i < _usSize; i++)
|
||||
{
|
||||
_pReadBuf[i] = i2c_ReadByte(); /* 读1个字节 */
|
||||
|
||||
/* 每读完1个字节后,需要发送Ack, 最后一个字节不需要Ack,发Nack */
|
||||
if (i != _usSize - 1)
|
||||
{
|
||||
i2c_Ack(); /* 中间字节读完后,CPU产生ACK信号(驱动SDA = 0) */
|
||||
}
|
||||
else
|
||||
{
|
||||
i2c_NAck(); /* 最后1个字节读完后,CPU产生NACK信号(驱动SDA = 1) */
|
||||
}
|
||||
}
|
||||
/* 发送I2C总线停止信号 */
|
||||
i2c_Stop();
|
||||
return 1; /* 执行成功 */
|
||||
|
||||
cmd_fail: /* 命令执行失败后,切记发送停止信号,避免影响I2C总线上其他设备 */
|
||||
/* 发送I2C总线停止信号 */
|
||||
i2c_Stop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: ee_WriteBytes
|
||||
* 功能说明: 向串行EEPROM指定地址写入若干数据,采用页写操作提高写入效率
|
||||
* 形 参: _usAddress : 起始地址
|
||||
* _usSize : 数据长度,单位为字节
|
||||
* _pWriteBuf : 存放读到的数据的缓冲区指针
|
||||
* 返 回 值: 0 表示失败,1表示成功
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
uint8_t ee_WriteBytes(uint8_t *_pWriteBuf, uint16_t _usAddress, uint16_t _usSize)
|
||||
{
|
||||
uint16_t i, m;
|
||||
uint16_t usAddr;
|
||||
|
||||
/*
|
||||
写串行EEPROM不像读操作可以连续读取很多字节,每次写操作只能在同一个page。
|
||||
对于24xx02,page size = 8
|
||||
简单的处理方法为:按字节写操作模式,每写1个字节,都发送地址
|
||||
为了提高连续写的效率: 本函数采用page wirte操作。
|
||||
*/
|
||||
|
||||
usAddr = _usAddress;
|
||||
for (i = 0; i < _usSize; i++)
|
||||
{
|
||||
/* 当发送第1个字节或是页面首地址时,需要重新发起启动信号和地址 */
|
||||
if ((i == 0) || (usAddr & (EE_PAGE_SIZE - 1)) == 0)
|
||||
{
|
||||
/* 第0步:发停止信号,启动内部写操作 */
|
||||
i2c_Stop();
|
||||
|
||||
/* 通过检查器件应答的方式,判断内部写操作是否完成, 一般小于 10ms
|
||||
CLK频率为200KHz时,查询次数为30次左右
|
||||
*/
|
||||
for (m = 0; m < 1000; m++)
|
||||
{
|
||||
/* 第1步:发起I2C总线启动信号 */
|
||||
i2c_Start();
|
||||
|
||||
/* 第2步:发起控制字节,高7bit是地址,bit0是读写控制位,0表示写,1表示读 */
|
||||
i2c_SendByte(EE_DEV_ADDR | I2C_WR); /* 此处是写指令 */
|
||||
|
||||
/* 第3步:发送一个时钟,判断器件是否正确应答 */
|
||||
if (i2c_WaitAck() == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (m == 1000)
|
||||
{
|
||||
goto cmd_fail; /* EEPROM器件写超时 */
|
||||
}
|
||||
|
||||
/* 第4步:发送字节地址,24C02只有256字节,因此1个字节就够了,如果是24C04以上,那么此处需要连发多个地址 */
|
||||
if (EE_ADDR_BYTES == 1)
|
||||
{
|
||||
i2c_SendByte((uint8_t)usAddr);
|
||||
if (i2c_WaitAck() != 0)
|
||||
{
|
||||
goto cmd_fail; /* EEPROM器件无应答 */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
i2c_SendByte(usAddr >> 8);
|
||||
if (i2c_WaitAck() != 0)
|
||||
{
|
||||
goto cmd_fail; /* EEPROM器件无应答 */
|
||||
}
|
||||
|
||||
i2c_SendByte(usAddr);
|
||||
if (i2c_WaitAck() != 0)
|
||||
{
|
||||
goto cmd_fail; /* EEPROM器件无应答 */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 第6步:开始写入数据 */
|
||||
i2c_SendByte(_pWriteBuf[i]);
|
||||
|
||||
/* 第7步:发送ACK */
|
||||
if (i2c_WaitAck() != 0)
|
||||
{
|
||||
goto cmd_fail; /* EEPROM器件无应答 */
|
||||
}
|
||||
|
||||
usAddr++; /* 地址增1 */
|
||||
}
|
||||
|
||||
/* 命令执行成功,发送I2C总线停止信号 */
|
||||
i2c_Stop();
|
||||
return 1;
|
||||
|
||||
cmd_fail: /* 命令执行失败后,切记发送停止信号,避免影响I2C总线上其他设备 */
|
||||
/* 发送I2C总线停止信号 */
|
||||
i2c_Stop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
|
||||
305
User/bsp/src/bsp_i2c_gpio.c
Normal file
305
User/bsp/src/bsp_i2c_gpio.c
Normal file
@@ -0,0 +1,305 @@
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
*
|
||||
* 模块名称 : I2C总线驱动模块
|
||||
* 文件名称 : bsp_i2c_gpio.c
|
||||
* 版 本 : V1.0
|
||||
* 说 明 : 用gpio模拟i2c总线, 适用于STM32F4系列CPU。该模块不包括应用层命令帧,仅包括I2C总线基本操作函数。
|
||||
*
|
||||
* 修改记录 :
|
||||
* 版本号 日期 作者 说明
|
||||
* V1.0 2015-05-21 armfly 正式发布
|
||||
*
|
||||
* Copyright (C), 2015-2016, 安富莱电子 www.armfly.com
|
||||
*
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
应用说明:
|
||||
在访问I2C设备前,请先调用 i2c_CheckDevice() 检测I2C设备是否正常,该函数会配置GPIO
|
||||
*/
|
||||
|
||||
#include "bsp.h"
|
||||
|
||||
/*
|
||||
安富莱STM32-V4开发板 i2c总线GPIO:
|
||||
PB6/I2C1_SCL
|
||||
PB7/I2C1_SDA
|
||||
*/
|
||||
|
||||
/* 定义I2C总线连接的GPIO端口, 用户只需要修改下面4行代码即可任意改变SCL和SDA的引脚 */
|
||||
|
||||
#define RCC_I2C_PORT RCC_APB2Periph_GPIOB /* GPIO端口时钟 */
|
||||
|
||||
#define PORT_I2C_SCL GPIOB /* GPIO端口 */
|
||||
#define PIN_I2C_SCL GPIO_Pin_6 /* GPIO引脚 */
|
||||
|
||||
#define PORT_I2C_SDA GPIOB /* GPIO端口 */
|
||||
#define PIN_I2C_SDA GPIO_Pin_7 /* GPIO引脚 */
|
||||
|
||||
#define I2C_SCL_PIN GPIO_Pin_6 /* 连接到SCL时钟线的GPIO */
|
||||
#define I2C_SDA_PIN GPIO_Pin_7 /* 连接到SDA数据线的GPIO */
|
||||
|
||||
/* 定义读写SCL和SDA的宏 */
|
||||
#define I2C_SCL_1() PORT_I2C_SCL->BSRR = I2C_SCL_PIN /* SCL = 1 */
|
||||
#define I2C_SCL_0() PORT_I2C_SCL->BRR = I2C_SCL_PIN /* SCL = 0 */
|
||||
|
||||
#define I2C_SDA_1() PORT_I2C_SDA->BSRR = I2C_SDA_PIN /* SDA = 1 */
|
||||
#define I2C_SDA_0() PORT_I2C_SDA->BRR = I2C_SDA_PIN /* SDA = 0 */
|
||||
|
||||
#define I2C_SDA_READ() ((PORT_I2C_SDA->IDR & I2C_SDA_PIN) != 0) /* 读SDA口线状态 */
|
||||
#define I2C_SCL_READ() ((PORT_I2C_SCL->IDR & I2C_SCL_PIN) != 0) /* 读SCL口线状态 */
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_InitI2C
|
||||
* 功能说明: 配置I2C总线的GPIO,采用模拟IO的方式实现
|
||||
* 形 参: 无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void bsp_InitI2C(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
RCC_APB2PeriphClockCmd(RCC_I2C_PORT, ENABLE); /* 打开GPIO时钟 */
|
||||
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; /* 开漏输出模式 */
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = PIN_I2C_SCL;
|
||||
GPIO_Init(PORT_I2C_SCL, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = PIN_I2C_SDA;
|
||||
GPIO_Init(PORT_I2C_SDA, &GPIO_InitStructure);
|
||||
|
||||
/* 给一个停止信号, 复位I2C总线上的所有设备到待机模式 */
|
||||
i2c_Stop();
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: i2c_Delay
|
||||
* 功能说明: I2C总线位延迟,最快400KHz
|
||||
* 形 参: 无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
static void i2c_Delay(void)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
/*
|
||||
CPU主频168MHz时,在内部Flash运行, MDK工程不优化。用台式示波器观测波形。
|
||||
循环次数为5时,SCL频率 = 1.78MHz (读耗时: 92ms, 读写正常,但是用示波器探头碰上就读写失败。时序接近临界)
|
||||
循环次数为10时,SCL频率 = 1.1MHz (读耗时: 138ms, 读速度: 118724B/s)
|
||||
循环次数为30时,SCL频率 = 440KHz, SCL高电平时间1.0us,SCL低电平时间1.2us
|
||||
|
||||
上拉电阻选择2.2K欧时,SCL上升沿时间约0.5us,如果选4.7K欧,则上升沿约1us
|
||||
|
||||
实际应用选择400KHz左右的速率即可
|
||||
*/
|
||||
for (i = 0; i < 30; i++)
|
||||
;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: i2c_Start
|
||||
* 功能说明: CPU发起I2C总线启动信号
|
||||
* 形 参: 无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void i2c_Start(void)
|
||||
{
|
||||
/* 当SCL高电平时,SDA出现一个下跳沿表示I2C总线启动信号 */
|
||||
I2C_SDA_1();
|
||||
I2C_SCL_1();
|
||||
i2c_Delay();
|
||||
I2C_SDA_0();
|
||||
i2c_Delay();
|
||||
|
||||
I2C_SCL_0();
|
||||
i2c_Delay();
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: i2c_Start
|
||||
* 功能说明: CPU发起I2C总线停止信号
|
||||
* 形 参: 无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void i2c_Stop(void)
|
||||
{
|
||||
/* 当SCL高电平时,SDA出现一个上跳沿表示I2C总线停止信号 */
|
||||
I2C_SDA_0();
|
||||
I2C_SCL_1();
|
||||
i2c_Delay();
|
||||
I2C_SDA_1();
|
||||
i2c_Delay();
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: i2c_SendByte
|
||||
* 功能说明: CPU向I2C总线设备发送8bit数据
|
||||
* 形 参: _ucByte : 等待发送的字节
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void i2c_SendByte(uint8_t _ucByte)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
/* 先发送字节的高位bit7 */
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
if (_ucByte & 0x80)
|
||||
{
|
||||
I2C_SDA_1();
|
||||
}
|
||||
else
|
||||
{
|
||||
I2C_SDA_0();
|
||||
}
|
||||
i2c_Delay();
|
||||
I2C_SCL_1();
|
||||
i2c_Delay();
|
||||
I2C_SCL_0();
|
||||
if (i == 7)
|
||||
{
|
||||
I2C_SDA_1(); // 释放总线
|
||||
}
|
||||
_ucByte <<= 1; /* 左移一个bit */
|
||||
i2c_Delay();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: i2c_ReadByte
|
||||
* 功能说明: CPU从I2C总线设备读取8bit数据
|
||||
* 形 参: 无
|
||||
* 返 回 值: 读到的数据
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
uint8_t i2c_ReadByte(void)
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t value;
|
||||
|
||||
/* 读到第1个bit为数据的bit7 */
|
||||
value = 0;
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
value <<= 1;
|
||||
I2C_SCL_1();
|
||||
i2c_Delay();
|
||||
if (I2C_SDA_READ())
|
||||
{
|
||||
value++;
|
||||
}
|
||||
I2C_SCL_0();
|
||||
i2c_Delay();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: i2c_WaitAck
|
||||
* 功能说明: CPU产生一个时钟,并读取器件的ACK应答信号
|
||||
* 形 参: 无
|
||||
* 返 回 值: 返回0表示正确应答,1表示无器件响应
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
uint8_t i2c_WaitAck(void)
|
||||
{
|
||||
uint8_t re;
|
||||
|
||||
I2C_SDA_1(); /* CPU释放SDA总线 */
|
||||
i2c_Delay();
|
||||
I2C_SCL_1(); /* CPU驱动SCL = 1, 此时器件会返回ACK应答 */
|
||||
i2c_Delay();
|
||||
if (I2C_SDA_READ()) /* CPU读取SDA口线状态 */
|
||||
{
|
||||
re = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
re = 0;
|
||||
}
|
||||
I2C_SCL_0();
|
||||
i2c_Delay();
|
||||
return re;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: i2c_Ack
|
||||
* 功能说明: CPU产生一个ACK信号
|
||||
* 形 参: 无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void i2c_Ack(void)
|
||||
{
|
||||
I2C_SDA_0(); /* CPU驱动SDA = 0 */
|
||||
i2c_Delay();
|
||||
I2C_SCL_1(); /* CPU产生1个时钟 */
|
||||
i2c_Delay();
|
||||
I2C_SCL_0();
|
||||
i2c_Delay();
|
||||
I2C_SDA_1(); /* CPU释放SDA总线 */
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: i2c_NAck
|
||||
* 功能说明: CPU产生1个NACK信号
|
||||
* 形 参: 无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void i2c_NAck(void)
|
||||
{
|
||||
I2C_SDA_1(); /* CPU驱动SDA = 1 */
|
||||
i2c_Delay();
|
||||
I2C_SCL_1(); /* CPU产生1个时钟 */
|
||||
i2c_Delay();
|
||||
I2C_SCL_0();
|
||||
i2c_Delay();
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: i2c_CheckDevice
|
||||
* 功能说明: 检测I2C总线设备,CPU向发送设备地址,然后读取设备应答来判断该设备是否存在
|
||||
* 形 参: _Address:设备的I2C总线地址
|
||||
* 返 回 值: 返回值 0 表示正确, 返回1表示未探测到
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
uint8_t i2c_CheckDevice(uint8_t _Address)
|
||||
{
|
||||
uint8_t ucAck;
|
||||
|
||||
if (I2C_SDA_READ() && I2C_SCL_READ())
|
||||
{
|
||||
i2c_Start(); /* 发送启动信号 */
|
||||
|
||||
/* 发送设备地址+读写控制bit(0 = w, 1 = r) bit7 先传 */
|
||||
i2c_SendByte(_Address | I2C_WR);
|
||||
ucAck = i2c_WaitAck(); /* 检测设备的ACK应答 */
|
||||
|
||||
i2c_Stop(); /* 发送停止信号 */
|
||||
|
||||
return ucAck;
|
||||
}
|
||||
return 1; /* I2C总线异常 */
|
||||
}
|
||||
|
||||
/***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
|
||||
496
User/bsp/src/bsp_key.c
Normal file
496
User/bsp/src/bsp_key.c
Normal file
@@ -0,0 +1,496 @@
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
*
|
||||
* 模块名称 : 独立按键驱动模块
|
||||
* 文件名称 : bsp_key.c
|
||||
* 版 本 : V1.0
|
||||
* 说 明 : 扫描独立按键,具有软件滤波机制,具有按键FIFO。可以检测如下事件:
|
||||
* (1) 按键按下
|
||||
* (2) 按键弹起
|
||||
* (3) 长按键
|
||||
* (4) 长按时自动连发
|
||||
*
|
||||
* 修改记录 :
|
||||
* 版本号 日期 作者 说明
|
||||
* V1.0 2013-02-01 armfly 正式发布
|
||||
* V1.1 2013-06-29 armfly 增加1个读指针,用于bsp_Idle() 函数读取系统控制组合键(截屏)
|
||||
* 增加 K1 K2 组合键 和 K2 K3 组合键,用于系统控制
|
||||
* V1.2 2015-08-08 armfly K1,K2,K3独立按键进行排他判断,修改 IsKeyDown1()等函数
|
||||
*
|
||||
* Copyright (C), 2015-2016, 安富莱电子 www.armfly.com
|
||||
*
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#include "bsp.h"
|
||||
|
||||
/*
|
||||
该程序适用于安富莱STM32-V4开发板
|
||||
|
||||
如果用于其它硬件,请修改GPIO定义和 IsKeyDown1 - IsKeyDown8 函数
|
||||
|
||||
如果用户的按键个数小于8个,你可以将多余的按键全部定义为和第1个按键一样,并不影响程序功能
|
||||
#define KEY_COUNT 8 这个在 bsp_key.h 文件中定义
|
||||
*/
|
||||
|
||||
/*
|
||||
安富莱STM32-V4 按键口线分配:
|
||||
K1 键 : PC13 (低电平表示按下)
|
||||
K2 键 : PA0 ( --- 高电平表示按下)
|
||||
K3 键 : PG8 (低电平表示按下)
|
||||
摇杆UP键 : PG15 (低电平表示按下)
|
||||
摇杆DOWN键 : PD3 (低电平表示按下)
|
||||
摇杆LEFT键 : PG14 (低电平表示按下)
|
||||
摇杆RIGHT键: PG13 (低电平表示按下)
|
||||
摇杆OK键 : PG7 (低电平表示按下)
|
||||
*/
|
||||
|
||||
/* 按键口对应的RCC时钟 */
|
||||
#define RCC_ALL_KEY RCC_APB2Periph_GPIOE
|
||||
#define RCC_ALL_KEY1 RCC_APB2Periph_GPIOA
|
||||
|
||||
#define GPIO_PORT_K6 GPIOA
|
||||
#define GPIO_PIN_K6 GPIO_Pin_3
|
||||
|
||||
#define GPIO_PORT_K1 GPIOE //(PE2)
|
||||
#define GPIO_PIN_K1 GPIO_Pin_2
|
||||
|
||||
#define GPIO_PORT_K2 GPIOE //(PE3)
|
||||
#define GPIO_PIN_K2 GPIO_Pin_3
|
||||
|
||||
static KEY_T s_tBtn[KEY_COUNT];
|
||||
static KEY_FIFO_T s_tKey; /* 按键FIFO变量,结构体 */
|
||||
|
||||
static void bsp_InitKeyVar(void);
|
||||
static void bsp_InitKeyHard(void);
|
||||
static void bsp_DetectKey(uint8_t i);
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: IsKeyDownX
|
||||
* 功能说明: 判断按键是否按下
|
||||
* 形 参: 无
|
||||
* 返 回 值: 返回值1 表示按下,0表示未按下
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
/* 安富莱 STM32-V4 开发板 */
|
||||
#if 0 /* 为了区分3个事件: K1单独按下, K2单独按下, K1和K2同时按下 */
|
||||
static uint8_t IsKeyDown1(void)
|
||||
{
|
||||
if ((GPIO_PORT_K1->IDR & GPIO_PIN_K1) == 0 && (GPIO_PORT_K2->IDR & GPIO_PIN_K2) == 0
|
||||
&& (GPIO_PORT_K3->IDR & GPIO_PIN_K3) != 0)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
static uint8_t IsKeyDown2(void)
|
||||
{
|
||||
if ((GPIO_PORT_K1->IDR & GPIO_PIN_K1) != 0 && (GPIO_PORT_K2->IDR & GPIO_PIN_K2) != 0
|
||||
&& (GPIO_PORT_K3->IDR & GPIO_PIN_K3) != 0)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
static uint8_t IsKeyDown3(void)
|
||||
{
|
||||
if ((GPIO_PORT_K1->IDR & GPIO_PIN_K1) != 0 && (GPIO_PORT_K2->IDR & GPIO_PIN_K2) == 0
|
||||
&& (GPIO_PORT_K3->IDR & GPIO_PIN_K3) == 0)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
static uint8_t IsKeyDown9(void) /* K1 K2组合键 */
|
||||
{
|
||||
if ((GPIO_PORT_K1->IDR & GPIO_PIN_K1) == 0 && (GPIO_PORT_K2->IDR & GPIO_PIN_K2) != 0
|
||||
&& (GPIO_PORT_K3->IDR & GPIO_PIN_K3) != 0)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
static uint8_t IsKeyDown10(void) /* K2 K3组合键 */
|
||||
{
|
||||
if ((GPIO_PORT_K1->IDR & GPIO_PIN_K1) != 0 && (GPIO_PORT_K2->IDR & GPIO_PIN_K2) != 0
|
||||
&& (GPIO_PORT_K3->IDR & GPIO_PIN_K3) == 0)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
uint8_t IsKeyDown1(void)
|
||||
{
|
||||
if ((GPIO_PORT_K6->IDR & GPIO_PIN_K6) == 0)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
} // 复位键
|
||||
// 被main函数调用
|
||||
uint8_t IsKeyDown2(void)
|
||||
{
|
||||
if ((GPIO_PORT_K1->IDR & GPIO_PIN_K1) == 0)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
} // 模式切换键
|
||||
uint8_t IsKeyDown3(void)
|
||||
{
|
||||
if ((GPIO_PORT_K2->IDR & GPIO_PIN_K2) == 0)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
} // 模式切换键
|
||||
// static uint8_t IsKeyDown3(void) {if ((GPIO_PORT_K3->IDR & GPIO_PIN_K3) == 0) return 1;else return 0;}
|
||||
|
||||
// static uint8_t IsKeyDown9(void) {if (IsKeyDown1() && IsKeyDown2()) return 1;else return 0;} /* K1 K2组合键 */
|
||||
// static uint8_t IsKeyDown10(void) {if (IsKeyDown2() && IsKeyDown3()) return 1;else return 0;} /* K2 K3组合键 */
|
||||
#endif
|
||||
|
||||
/* 5方向摇杆 */
|
||||
// static uint8_t IsKeyDown4(void) {if ((GPIO_PORT_K4->IDR & GPIO_PIN_K4) == 0) return 1;else return 0;}
|
||||
// static uint8_t IsKeyDown5(void) {if ((GPIO_PORT_K5->IDR & GPIO_PIN_K5) == 0) return 1;else return 0;}
|
||||
// static uint8_t IsKeyDown6(void) {if ((GPIO_PORT_K6->IDR & GPIO_PIN_K6) == 0) return 1;else return 0;}
|
||||
// static uint8_t IsKeyDown7(void) {if ((GPIO_PORT_K7->IDR & GPIO_PIN_K7) == 0) return 1;else return 0;}
|
||||
// static uint8_t IsKeyDown8(void) {if ((GPIO_PORT_K8->IDR & GPIO_PIN_K8) == 0) return 1;else return 0;}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_InitKey
|
||||
* 功能说明: 初始化按键. 该函数被 bsp_Init() 调用。
|
||||
* 形 参: 无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void bsp_InitKey(void)
|
||||
{
|
||||
bsp_InitKeyVar(); /* 初始化按键变量 */
|
||||
bsp_InitKeyHard(); /* 初始化按键硬件 */
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_PutKey
|
||||
* 功能说明: 将1个键值压入按键FIFO缓冲区。可用于模拟一个按键。
|
||||
* 形 参: _KeyCode : 按键代码
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void bsp_PutKey(uint8_t _KeyCode)
|
||||
{
|
||||
s_tKey.Buf[s_tKey.Write] = _KeyCode;
|
||||
|
||||
if (++s_tKey.Write >= KEY_FIFO_SIZE)
|
||||
{
|
||||
s_tKey.Write = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_GetKey
|
||||
* 功能说明: 从按键FIFO缓冲区读取一个键值。
|
||||
* 形 参: 无
|
||||
* 返 回 值: 按键代码
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
uint8_t bsp_GetKey(void)
|
||||
{
|
||||
uint8_t ret;
|
||||
|
||||
if (s_tKey.Read == s_tKey.Write)
|
||||
{
|
||||
return KEY_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = s_tKey.Buf[s_tKey.Read];
|
||||
|
||||
if (++s_tKey.Read >= KEY_FIFO_SIZE)
|
||||
{
|
||||
s_tKey.Read = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_GetKey2
|
||||
* 功能说明: 从按键FIFO缓冲区读取一个键值。独立的读指针。
|
||||
* 形 参: 无
|
||||
* 返 回 值: 按键代码
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
uint8_t bsp_GetKey2(void)
|
||||
{
|
||||
uint8_t ret;
|
||||
|
||||
if (s_tKey.Read2 == s_tKey.Write)
|
||||
{
|
||||
return KEY_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = s_tKey.Buf[s_tKey.Read2];
|
||||
|
||||
if (++s_tKey.Read2 >= KEY_FIFO_SIZE)
|
||||
{
|
||||
s_tKey.Read2 = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_GetKeyState
|
||||
* 功能说明: 读取按键的状态
|
||||
* 形 参: _ucKeyID : 按键ID,从0开始
|
||||
* 返 回 值: 1 表示按下, 0 表示未按下
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
uint8_t bsp_GetKeyState(KEY_ID_E _ucKeyID)
|
||||
{
|
||||
return s_tBtn[_ucKeyID].State;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_SetKeyParam
|
||||
* 功能说明: 设置按键参数
|
||||
* 形 参:_ucKeyID : 按键ID,从0开始
|
||||
* _LongTime : 长按事件时间
|
||||
* _RepeatSpeed : 连发速度
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void bsp_SetKeyParam(uint8_t _ucKeyID, uint16_t _LongTime, uint8_t _RepeatSpeed)
|
||||
{
|
||||
s_tBtn[_ucKeyID].LongTime = _LongTime; /* 长按时间 0 表示不检测长按键事件 */
|
||||
s_tBtn[_ucKeyID].RepeatSpeed = _RepeatSpeed; /* 按键连发的速度,0表示不支持连发 */
|
||||
s_tBtn[_ucKeyID].RepeatCount = 0; /* 连发计数器 */
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_ClearKey
|
||||
* 功能说明: 清空按键FIFO缓冲区
|
||||
* 形 参:无
|
||||
* 返 回 值: 按键代码
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void bsp_ClearKey(void)
|
||||
{
|
||||
s_tKey.Read = s_tKey.Write;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_InitKeyHard
|
||||
* 功能说明: 配置按键对应的GPIO
|
||||
* 形 参: 无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
static void bsp_InitKeyHard(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
/* 第1步:打开GPIO时钟 */
|
||||
RCC_APB2PeriphClockCmd(RCC_ALL_KEY | RCC_ALL_KEY1, ENABLE);
|
||||
|
||||
/* 第2步:配置所有的按键GPIO为浮动输入模式(实际上CPU复位后就是输入状态) */
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; /* 输入浮空模式 */
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_K1;
|
||||
GPIO_Init(GPIO_PORT_K1, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_K2;
|
||||
GPIO_Init(GPIO_PORT_K2, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_K6;
|
||||
GPIO_Init(GPIO_PORT_K6, &GPIO_InitStructure);
|
||||
|
||||
// GPIO_InitStructure.GPIO_Pin = GPIO_PIN_K3;
|
||||
// GPIO_Init(GPIO_PORT_K3, &GPIO_InitStructure);
|
||||
//
|
||||
// GPIO_InitStructure.GPIO_Pin = GPIO_PIN_K4;
|
||||
// GPIO_Init(GPIO_PORT_K4, &GPIO_InitStructure);
|
||||
//
|
||||
// GPIO_InitStructure.GPIO_Pin = GPIO_PIN_K5;
|
||||
// GPIO_Init(GPIO_PORT_K5, &GPIO_InitStructure);
|
||||
//
|
||||
// GPIO_InitStructure.GPIO_Pin = GPIO_PIN_K6;
|
||||
// GPIO_Init(GPIO_PORT_K6, &GPIO_InitStructure);
|
||||
//
|
||||
// GPIO_InitStructure.GPIO_Pin = GPIO_PIN_K7;
|
||||
// GPIO_Init(GPIO_PORT_K7, &GPIO_InitStructure);
|
||||
//
|
||||
// GPIO_InitStructure.GPIO_Pin = GPIO_PIN_K8;
|
||||
// GPIO_Init(GPIO_PORT_K8, &GPIO_InitStructure);
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_InitKeyVar
|
||||
* 功能说明: 初始化按键变量
|
||||
* 形 参: 无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
static void bsp_InitKeyVar(void)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
/* 对按键FIFO读写指针清零 */
|
||||
s_tKey.Read = 0;
|
||||
s_tKey.Write = 0;
|
||||
s_tKey.Read2 = 0;
|
||||
|
||||
/* 给每个按键结构体成员变量赋一组缺省值 */
|
||||
for (i = 0; i < KEY_COUNT; i++)
|
||||
{
|
||||
s_tBtn[i].LongTime = KEY_LONG_TIME; /* 长按时间 0 表示不检测长按键事件 */
|
||||
s_tBtn[i].Count = KEY_FILTER_TIME / 2; /* 计数器设置为滤波时间的一半 */
|
||||
s_tBtn[i].State = 0; /* 按键缺省状态,0为未按下 */
|
||||
// s_tBtn[i].KeyCodeDown = 3 * i + 1; /* 按键按下的键值代码 */
|
||||
// s_tBtn[i].KeyCodeUp = 3 * i + 2; /* 按键弹起的键值代码 */
|
||||
// s_tBtn[i].KeyCodeLong = 3 * i + 3; /* 按键被持续按下的键值代码 */
|
||||
s_tBtn[i].RepeatSpeed = 0; /* 按键连发的速度,0表示不支持连发 */
|
||||
s_tBtn[i].RepeatCount = 0; /* 连发计数器 */
|
||||
}
|
||||
|
||||
/* 如果需要单独更改某个按键的参数,可以在此单独重新赋值 */
|
||||
/* 比如,我们希望按键1按下超过1秒后,自动重发相同键值 */
|
||||
// s_tBtn[KID_K7].LongTime = 40;
|
||||
// s_tBtn[KID_K7].RepeatSpeed = 5; /* 每隔50ms自动发送键值 */
|
||||
//
|
||||
// s_tBtn[KID_K8].LongTime = 40;
|
||||
// s_tBtn[KID_K8].RepeatSpeed = 5; /* 每隔50ms自动发送键值 */
|
||||
|
||||
/* 判断按键按下的函数 */
|
||||
s_tBtn[0].IsKeyDownFunc = IsKeyDown1;
|
||||
s_tBtn[1].IsKeyDownFunc = IsKeyDown2;
|
||||
s_tBtn[2].IsKeyDownFunc = IsKeyDown3;
|
||||
// s_tBtn[3].IsKeyDownFunc = IsKeyDown4;
|
||||
// s_tBtn[4].IsKeyDownFunc = IsKeyDown5;
|
||||
// s_tBtn[5].IsKeyDownFunc = IsKeyDown6;
|
||||
// s_tBtn[6].IsKeyDownFunc = IsKeyDown7;// shen 0809
|
||||
// s_tBtn[7].IsKeyDownFunc = IsKeyDown8;
|
||||
|
||||
/* 组合键 */
|
||||
// s_tBtn[8].IsKeyDownFunc = IsKeyDown9;
|
||||
// s_tBtn[9].IsKeyDownFunc = IsKeyDown10;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_DetectKey
|
||||
* 功能说明: 检测一个按键。非阻塞状态,必须被周期性的调用。
|
||||
* 形 参: 按键结构变量指针
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
static void bsp_DetectKey(uint8_t i)
|
||||
{
|
||||
KEY_T *pBtn;
|
||||
|
||||
/*
|
||||
如果没有初始化按键函数,则报错
|
||||
if (s_tBtn[i].IsKeyDownFunc == 0)
|
||||
{
|
||||
printf("Fault : DetectButton(), s_tBtn[i].IsKeyDownFunc undefine");
|
||||
}
|
||||
*/
|
||||
|
||||
pBtn = &s_tBtn[i];
|
||||
if (pBtn->IsKeyDownFunc())
|
||||
{
|
||||
if (pBtn->Count < KEY_FILTER_TIME)
|
||||
{
|
||||
pBtn->Count = KEY_FILTER_TIME;
|
||||
}
|
||||
else if (pBtn->Count < 2 * KEY_FILTER_TIME)
|
||||
{
|
||||
pBtn->Count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pBtn->State == 0)
|
||||
{
|
||||
pBtn->State = 1;
|
||||
|
||||
/* 发送按钮按下的消息 */
|
||||
bsp_PutKey((uint8_t)(3 * i + 1));
|
||||
}
|
||||
|
||||
if (pBtn->LongTime > 0)
|
||||
{
|
||||
if (pBtn->LongCount < pBtn->LongTime)
|
||||
{
|
||||
/* 发送按钮持续按下的消息 */
|
||||
if (++pBtn->LongCount == pBtn->LongTime)
|
||||
{
|
||||
/* 键值放入按键FIFO */
|
||||
bsp_PutKey((uint8_t)(3 * i + 3));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pBtn->RepeatSpeed > 0)
|
||||
{
|
||||
if (++pBtn->RepeatCount >= pBtn->RepeatSpeed)
|
||||
{
|
||||
pBtn->RepeatCount = 0;
|
||||
/* 常按键后,每隔10ms发送1个按键 */
|
||||
bsp_PutKey((uint8_t)(3 * i + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pBtn->Count > KEY_FILTER_TIME)
|
||||
{
|
||||
pBtn->Count = KEY_FILTER_TIME;
|
||||
}
|
||||
else if (pBtn->Count != 0)
|
||||
{
|
||||
pBtn->Count--;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pBtn->State == 1)
|
||||
{
|
||||
pBtn->State = 0;
|
||||
|
||||
/* 发送按钮弹起的消息 */
|
||||
bsp_PutKey((uint8_t)(3 * i + 2));
|
||||
}
|
||||
}
|
||||
|
||||
pBtn->LongCount = 0;
|
||||
pBtn->RepeatCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_KeyScan
|
||||
* 功能说明: 扫描所有按键。非阻塞,被systick中断周期性的调用
|
||||
* 形 参: 无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void bsp_KeyScan(void)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < KEY_COUNT; i++)
|
||||
{
|
||||
bsp_DetectKey(i);
|
||||
}
|
||||
}
|
||||
|
||||
/***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
|
||||
445
User/bsp/src/bsp_led.c
Normal file
445
User/bsp/src/bsp_led.c
Normal file
@@ -0,0 +1,445 @@
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
*
|
||||
* 模块名称 : LED指示灯驱动模块
|
||||
* 文件名称 : bsp_led.c
|
||||
* 版 本 : V1.0
|
||||
* 说 明 : 驱动LED指示灯
|
||||
*
|
||||
* 修改记录 :
|
||||
* 版本号 日期 作者 说明
|
||||
* V1.0 2013-02-01 armfly 正式发布
|
||||
*
|
||||
* Copyright (C), 2013-2014, 安富莱电子 www.armfly.com
|
||||
*
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#include "bsp.h"
|
||||
|
||||
/*
|
||||
该程序适用于安富莱STM32-V4 开发板
|
||||
|
||||
如果用于其它硬件,请修改GPIO定义
|
||||
|
||||
如果用户的LED指示灯个数小于4个,可以将多余的LED全部定义为和第1个LED一样,并不影响程序功能
|
||||
*/
|
||||
|
||||
|
||||
/* 按键口对应的RCC时钟 */
|
||||
#define RCC_ALL_LED (RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE | RCC_APB2Periph_GPIOF)
|
||||
|
||||
#define GPIO_PORT_LED1 GPIOA
|
||||
#define GPIO_PIN_LED1 GPIO_Pin_15
|
||||
|
||||
#define GPIO_PORT_LED2 GPIOC
|
||||
#define GPIO_PIN_LED2 GPIO_Pin_10
|
||||
|
||||
#define GPIO_PORT_LED3 GPIOC
|
||||
#define GPIO_PIN_LED3 GPIO_Pin_11
|
||||
|
||||
#define GPIO_PORT_LED4 GPIOC
|
||||
#define GPIO_PIN_LED4 GPIO_Pin_12
|
||||
|
||||
#define GPIO_PORT_LED5 GPIOD
|
||||
#define GPIO_PIN_LED5 GPIO_Pin_0
|
||||
|
||||
#define GPIO_PORT_LED6 GPIOD
|
||||
#define GPIO_PIN_LED6 GPIO_Pin_1
|
||||
|
||||
#define GPIO_PORT_LED7 GPIOF
|
||||
#define GPIO_PIN_LED7 GPIO_Pin_5
|
||||
|
||||
#define GPIO_PORT_LED8 GPIOF
|
||||
#define GPIO_PIN_LED8 GPIO_Pin_4
|
||||
|
||||
#define GPIO_PORT_LED9 GPIOF
|
||||
#define GPIO_PIN_LED9 GPIO_Pin_3
|
||||
|
||||
#define GPIO_PORT_LED10 GPIOF
|
||||
#define GPIO_PIN_LED10 GPIO_Pin_2
|
||||
|
||||
#define GPIO_PORT_LED11 GPIOF
|
||||
#define GPIO_PIN_LED11 GPIO_Pin_1
|
||||
|
||||
#define GPIO_PORT_LED12 GPIOF
|
||||
#define GPIO_PIN_LED12 GPIO_Pin_0
|
||||
|
||||
#define GPIO_PORT_LED13 GPIOE
|
||||
#define GPIO_PIN_LED13 GPIO_Pin_5
|
||||
|
||||
#define GPIO_PORT_LED14 GPIOE
|
||||
#define GPIO_PIN_LED14 GPIO_Pin_4
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_InitLed
|
||||
* 功能说明: 配置LED指示灯相关的GPIO, 该函数被 bsp_Init() 调用。
|
||||
* 形 参: 无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void bsp_InitLed(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
/* 打开GPIO时钟 */
|
||||
RCC_APB2PeriphClockCmd(RCC_ALL_LED, ENABLE);
|
||||
|
||||
/*
|
||||
配置所有的LED指示灯GPIO为推挽输出模式
|
||||
由于将GPIO设置为输出时,GPIO输出寄存器的值缺省是0,因此会驱动LED点亮.
|
||||
这是我不希望的,因此在改变GPIO为输出前,先关闭LED指示灯
|
||||
*/
|
||||
bsp_LedOff(1);
|
||||
bsp_LedOff(2);
|
||||
bsp_LedOff(3);
|
||||
bsp_LedOff(4);
|
||||
bsp_LedOff(5);
|
||||
bsp_LedOff(6);
|
||||
bsp_LedOn(7);
|
||||
bsp_LedOff(8);
|
||||
bsp_LedOff(9);
|
||||
bsp_LedOff(10);
|
||||
bsp_LedOff(11);
|
||||
bsp_LedOff(12);
|
||||
bsp_LedOff(13);
|
||||
bsp_LedOff(14);
|
||||
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; /* 推挽输出模式 */
|
||||
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE);
|
||||
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_LED1;
|
||||
GPIO_Init(GPIO_PORT_LED1, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_LED2;
|
||||
GPIO_Init(GPIO_PORT_LED2, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_LED3;
|
||||
GPIO_Init(GPIO_PORT_LED3, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_LED4;
|
||||
GPIO_Init(GPIO_PORT_LED4, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_LED5;
|
||||
GPIO_Init(GPIO_PORT_LED5, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_LED6;
|
||||
GPIO_Init(GPIO_PORT_LED6, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_LED7;
|
||||
GPIO_Init(GPIO_PORT_LED7, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_LED8;
|
||||
GPIO_Init(GPIO_PORT_LED8, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_LED9;
|
||||
GPIO_Init(GPIO_PORT_LED9, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_LED10;
|
||||
GPIO_Init(GPIO_PORT_LED10, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_LED11;
|
||||
GPIO_Init(GPIO_PORT_LED11, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_LED12;
|
||||
GPIO_Init(GPIO_PORT_LED12, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_LED13;
|
||||
GPIO_Init(GPIO_PORT_LED13, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_LED14;
|
||||
GPIO_Init(GPIO_PORT_LED14, &GPIO_InitStructure);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_LedOn
|
||||
* 功能说明: 点亮指定的LED指示灯。
|
||||
* 形 参: _no : 指示灯序号,范围 1 - 4
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void bsp_LedOff(uint8_t _no)
|
||||
{
|
||||
_no--;
|
||||
|
||||
if (_no == 0)
|
||||
{
|
||||
GPIO_PORT_LED1->BRR = GPIO_PIN_LED1;
|
||||
}
|
||||
else if (_no == 1)
|
||||
{
|
||||
GPIO_PORT_LED2->BRR = GPIO_PIN_LED2;
|
||||
}
|
||||
else if (_no == 2)
|
||||
{
|
||||
GPIO_PORT_LED3->BRR = GPIO_PIN_LED3;
|
||||
}
|
||||
else if (_no == 3)
|
||||
{
|
||||
GPIO_PORT_LED4->BRR = GPIO_PIN_LED4;
|
||||
}
|
||||
else if (_no == 4)
|
||||
{
|
||||
GPIO_PORT_LED5->BRR = GPIO_PIN_LED5;
|
||||
}
|
||||
else if (_no == 5)
|
||||
{
|
||||
GPIO_PORT_LED6->BRR = GPIO_PIN_LED6;
|
||||
}
|
||||
else if (_no == 6)
|
||||
{
|
||||
GPIO_PORT_LED7->BRR = GPIO_PIN_LED7;
|
||||
}
|
||||
else if (_no == 7)
|
||||
{
|
||||
GPIO_PORT_LED8->BRR = GPIO_PIN_LED8;
|
||||
}
|
||||
else if (_no == 8)
|
||||
{
|
||||
GPIO_PORT_LED9->BRR = GPIO_PIN_LED9;
|
||||
}
|
||||
else if (_no == 9)
|
||||
{
|
||||
GPIO_PORT_LED10->BRR = GPIO_PIN_LED10;
|
||||
}
|
||||
else if (_no == 10)
|
||||
{
|
||||
GPIO_PORT_LED11->BRR = GPIO_PIN_LED11;
|
||||
}
|
||||
else if (_no == 11)
|
||||
{
|
||||
GPIO_PORT_LED12->BRR = GPIO_PIN_LED12;
|
||||
}
|
||||
else if (_no == 12)
|
||||
{
|
||||
GPIO_PORT_LED13->BRR = GPIO_PIN_LED13;
|
||||
}
|
||||
else if (_no == 13)
|
||||
{
|
||||
GPIO_PORT_LED14->BRR = GPIO_PIN_LED14;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_LedOff
|
||||
* 功能说明: 熄灭指定的LED指示灯。
|
||||
* 形 参: _no : 指示灯序号,范围 1 - 4
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void bsp_LedOn(uint8_t _no)
|
||||
{
|
||||
_no--;
|
||||
|
||||
if (_no == 0)
|
||||
{
|
||||
GPIO_PORT_LED1->BSRR = GPIO_PIN_LED1;
|
||||
}
|
||||
else if (_no == 1)
|
||||
{
|
||||
GPIO_PORT_LED2->BSRR = GPIO_PIN_LED2;
|
||||
}
|
||||
else if (_no == 2)
|
||||
{
|
||||
GPIO_PORT_LED3->BSRR = GPIO_PIN_LED3;
|
||||
}
|
||||
else if (_no == 3)
|
||||
{
|
||||
GPIO_PORT_LED4->BSRR = GPIO_PIN_LED4;
|
||||
}
|
||||
else if (_no == 4)
|
||||
{
|
||||
GPIO_PORT_LED5->BSRR = GPIO_PIN_LED5;
|
||||
}
|
||||
else if (_no == 5)
|
||||
{
|
||||
GPIO_PORT_LED6->BSRR = GPIO_PIN_LED6;
|
||||
}
|
||||
else if (_no == 6)
|
||||
{
|
||||
GPIO_PORT_LED7->BSRR = GPIO_PIN_LED7;
|
||||
}
|
||||
else if (_no == 7)
|
||||
{
|
||||
GPIO_PORT_LED8->BSRR = GPIO_PIN_LED8;
|
||||
}
|
||||
else if (_no == 8)
|
||||
{
|
||||
GPIO_PORT_LED9->BSRR = GPIO_PIN_LED9;
|
||||
}
|
||||
else if (_no == 9)
|
||||
{
|
||||
GPIO_PORT_LED10->BSRR = GPIO_PIN_LED10;
|
||||
}
|
||||
else if (_no == 10)
|
||||
{
|
||||
GPIO_PORT_LED11->BSRR = GPIO_PIN_LED11;
|
||||
}
|
||||
else if (_no == 11)
|
||||
{
|
||||
GPIO_PORT_LED12->BSRR = GPIO_PIN_LED12;
|
||||
}
|
||||
else if (_no == 12)
|
||||
{
|
||||
GPIO_PORT_LED13->BSRR = GPIO_PIN_LED13;
|
||||
}
|
||||
else if (_no == 13)
|
||||
{
|
||||
GPIO_PORT_LED14->BSRR = GPIO_PIN_LED14;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_LedToggle
|
||||
* 功能说明: 翻转指定的LED指示灯。
|
||||
* 形 参: _no : 指示灯序号,范围 1 - 4
|
||||
* 返 回 值: 按键代码
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void bsp_LedToggle(uint8_t _no)
|
||||
{
|
||||
if (_no == 1)
|
||||
{
|
||||
GPIO_PORT_LED1->ODR ^= GPIO_PIN_LED1;
|
||||
}
|
||||
else if (_no == 2)
|
||||
{
|
||||
GPIO_PORT_LED2->ODR ^= GPIO_PIN_LED2;
|
||||
}
|
||||
else if (_no == 3)
|
||||
{
|
||||
GPIO_PORT_LED3->ODR ^= GPIO_PIN_LED3;
|
||||
}
|
||||
else if (_no == 4)
|
||||
{
|
||||
GPIO_PORT_LED4->ODR ^= GPIO_PIN_LED4;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_IsLedOn
|
||||
* 功能说明: 判断LED指示灯是否已经点亮。
|
||||
* 形 参: _no : 指示灯序号,范围 1 - 4
|
||||
* 返 回 值: 1表示已经点亮,0表示未点亮
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
uint8_t bsp_IsLedOn(uint8_t _no)
|
||||
{
|
||||
if (_no == 1)
|
||||
{
|
||||
if ((GPIO_PORT_LED1->ODR & GPIO_PIN_LED1) == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if (_no == 2)
|
||||
{
|
||||
if ((GPIO_PORT_LED2->ODR & GPIO_PIN_LED2) == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if (_no == 3)
|
||||
{
|
||||
if ((GPIO_PORT_LED3->ODR & GPIO_PIN_LED3) == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if (_no == 4)
|
||||
{
|
||||
if ((GPIO_PORT_LED4->ODR & GPIO_PIN_LED4) == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bsp_LedAllOff(void)
|
||||
{
|
||||
bsp_LedOff(1);
|
||||
bsp_LedOff(2);
|
||||
bsp_LedOff(3);
|
||||
bsp_LedOff(4);
|
||||
bsp_LedOff(5);
|
||||
bsp_LedOff(6);
|
||||
bsp_LedOff(7);
|
||||
bsp_LedOff(8);
|
||||
bsp_LedOff(9);
|
||||
bsp_LedOff(10);
|
||||
bsp_LedOff(11);
|
||||
bsp_LedOff(12);
|
||||
bsp_LedOff(13);
|
||||
bsp_LedOff(14);
|
||||
}
|
||||
|
||||
static void ChannelLedAllOff(void)
|
||||
{
|
||||
bsp_LedOff(1);
|
||||
bsp_LedOff(2);
|
||||
bsp_LedOff(3);
|
||||
bsp_LedOff(4);
|
||||
bsp_LedOff(5);
|
||||
bsp_LedOff(6);
|
||||
}
|
||||
|
||||
static void ResLedAllOff(void)
|
||||
{
|
||||
bsp_LedOff(7);
|
||||
bsp_LedOff(8);
|
||||
bsp_LedOff(9);
|
||||
bsp_LedOff(10);
|
||||
bsp_LedOff(11);
|
||||
bsp_LedOff(12);
|
||||
bsp_LedOff(13);
|
||||
bsp_LedOff(14);
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
// ch = 1,2,3,4,5,6
|
||||
//---------------------------------------
|
||||
void bsp_ChannelSelect(uint8_t _ch)
|
||||
{
|
||||
static uint8_t s_ucOldCh=255;
|
||||
|
||||
if(_ch==s_ucOldCh)
|
||||
{
|
||||
ChannelLedAllOff();
|
||||
bsp_RealyAllOff();
|
||||
s_ucOldCh=255;
|
||||
}
|
||||
else
|
||||
{
|
||||
s_ucOldCh = _ch;
|
||||
ChannelLedAllOff();
|
||||
bsp_LedOn(_ch);
|
||||
bsp_RelayOn(_ch);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void bsp_ResSelect(uint8_t _res)
|
||||
{
|
||||
ResLedAllOff();
|
||||
//printf("_res:%d\r\n",_res);
|
||||
bsp_LedOn(_res);
|
||||
bsp_SelectRes(_res);
|
||||
}
|
||||
|
||||
/***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
|
||||
162
User/bsp/src/bsp_res.c
Normal file
162
User/bsp/src/bsp_res.c
Normal file
@@ -0,0 +1,162 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 模块名称:压电位移控制器串联电阻驱动模块
|
||||
// 文件名称:bsp_res.c
|
||||
// 版本名称:V1.0
|
||||
// 文件说明:控制IO选择外部串联电阻的大小
|
||||
// 日期时间:2018年8月8日15点14分
|
||||
// 文件作者:Jackie Chan
|
||||
// 修改记录:
|
||||
// 版本号 日期 作者 说明
|
||||
// V1.0 2018.08.08 J.C 正式发布
|
||||
//
|
||||
// 公司名称:多场低温科技有限公司
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#include "bsp.h"
|
||||
|
||||
// 控制串联电阻口对应的RCC时钟
|
||||
#define RCC_ALL_RES (RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC)
|
||||
|
||||
#define GPIO_PORT_RES10 GPIOC
|
||||
#define GPIO_PIN_RES10 GPIO_Pin_4
|
||||
|
||||
#define GPIO_PORT_RES51_1 GPIOC
|
||||
#define GPIO_PIN_RES51_1 GPIO_Pin_5
|
||||
|
||||
#define GPIO_PORT_RES51_2 GPIOB
|
||||
#define GPIO_PIN_RES51_2 GPIO_Pin_0
|
||||
|
||||
#define GPIO_PORT_RES100 GPIOB
|
||||
#define GPIO_PIN_RES100 GPIO_Pin_1
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// 函 数 名: bsp_InitRes
|
||||
// 功能说明: 配置串联电阻相关的GPIO, 该函数被 bsp_Init() 调用。
|
||||
// 形 参: 无
|
||||
// 返 回 值: 无
|
||||
//------------------------------------------------------------------------------
|
||||
void bsp_InitRes(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
// 打开GPIO时钟
|
||||
RCC_APB2PeriphClockCmd(RCC_ALL_RES, ENABLE);
|
||||
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; /* 推挽输出模式 */
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_RES10;
|
||||
GPIO_Init(GPIO_PORT_RES10, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_RES51_1;
|
||||
GPIO_Init(GPIO_PORT_RES51_1, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_RES51_2;
|
||||
GPIO_Init(GPIO_PORT_RES51_2, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_RES100;
|
||||
GPIO_Init(GPIO_PORT_RES100, &GPIO_InitStructure);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// 函 数 名: bsp_Port10_Output
|
||||
// 功能说明: 打开指定的电阻控制端口。
|
||||
// 形 参: _status : 电阻控制端口输出状态:0或者1
|
||||
// 返 回 值: 无
|
||||
//------------------------------------------------------------------------------
|
||||
void bsp_Port10_Output(uint8_t _status)
|
||||
{
|
||||
if(_status==0)
|
||||
{
|
||||
GPIO_PORT_RES10->BRR = GPIO_PIN_RES10;
|
||||
}
|
||||
else if(_status==1)
|
||||
{
|
||||
GPIO_PORT_RES10->BSRR = GPIO_PIN_RES10;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// 函 数 名: bsp_Port51_1_Output
|
||||
// 功能说明: 打开指定的电阻控制端口。
|
||||
// 形 参: _status : 电阻控制端口输出状态:0或者1
|
||||
// 返 回 值: 无
|
||||
//------------------------------------------------------------------------------
|
||||
void bsp_Port51_1_Output(uint8_t _status)
|
||||
{
|
||||
if(_status==0)
|
||||
{
|
||||
GPIO_PORT_RES51_1->BRR = GPIO_PIN_RES51_1;
|
||||
}
|
||||
else if(_status==1)
|
||||
{
|
||||
GPIO_PORT_RES51_1->BSRR = GPIO_PIN_RES51_1;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// 函 数 名: bsp_Port51_2_Output
|
||||
// 功能说明: 打开指定的电阻控制端口。
|
||||
// 形 参: _status : 电阻控制端口输出状态:0或者1
|
||||
// 返 回 值: 无
|
||||
//------------------------------------------------------------------------------
|
||||
void bsp_Port51_2_Output(uint8_t _status)
|
||||
{
|
||||
if(_status==0)
|
||||
{
|
||||
GPIO_PORT_RES51_2->BRR = GPIO_PIN_RES51_2;
|
||||
}
|
||||
else if(_status==1)
|
||||
{
|
||||
GPIO_PORT_RES51_2->BSRR = GPIO_PIN_RES51_2;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// 函 数 名: bsp_Port100_Output
|
||||
// 功能说明: 打开指定的电阻控制端口。
|
||||
// 形 参: _status : 电阻控制端口输出状态:0或者1
|
||||
// 返 回 值: 无
|
||||
//------------------------------------------------------------------------------
|
||||
void bsp_Port100_Output(uint8_t _status)
|
||||
{
|
||||
if(_status==0)
|
||||
{
|
||||
GPIO_PORT_RES100->BRR = GPIO_PIN_RES100;
|
||||
}
|
||||
else if(_status==1)
|
||||
{
|
||||
GPIO_PORT_RES100->BSRR = GPIO_PIN_RES100;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// 函 数 名: bsp_SelectRes
|
||||
// 功能说明: 打开指定的电阻控制端口组合。
|
||||
// 形 参: _res : 电阻控制端口输出状态:7~14
|
||||
// 返 回 值: 无
|
||||
//------------------------------------------------------------------------------
|
||||
void bsp_SelectRes(uint8_t _res)
|
||||
{
|
||||
switch(_res)
|
||||
{
|
||||
case RES_0:
|
||||
bsp_Port10_Output(0);bsp_Port51_1_Output(0);bsp_Port51_2_Output(0);bsp_Port100_Output(0); break;
|
||||
case RES_10:
|
||||
bsp_Port10_Output(1);bsp_Port51_1_Output(0);bsp_Port51_2_Output(0);bsp_Port100_Output(0); break;
|
||||
case RES_61:
|
||||
bsp_Port10_Output(1);bsp_Port51_1_Output(1);bsp_Port51_2_Output(0);bsp_Port100_Output(0); break;
|
||||
case RES_100:
|
||||
bsp_Port10_Output(0);bsp_Port51_1_Output(0);bsp_Port51_2_Output(0);bsp_Port100_Output(1); break;
|
||||
case RES_110:
|
||||
bsp_Port10_Output(1);bsp_Port51_1_Output(0);bsp_Port51_2_Output(0);bsp_Port100_Output(1); break;
|
||||
case RES_151:
|
||||
bsp_Port10_Output(0);bsp_Port51_1_Output(1);bsp_Port51_2_Output(0);bsp_Port100_Output(1); break;
|
||||
case RES_202:
|
||||
bsp_Port10_Output(0);bsp_Port51_1_Output(1);bsp_Port51_2_Output(1);bsp_Port100_Output(1); break;
|
||||
case RES_212:
|
||||
bsp_Port10_Output(1);bsp_Port51_1_Output(1);bsp_Port51_2_Output(1);bsp_Port100_Output(1); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------- End of file ---------------------------------
|
||||
250
User/bsp/src/bsp_step_moto.c
Normal file
250
User/bsp/src/bsp_step_moto.c
Normal file
@@ -0,0 +1,250 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 模块名称:步进电机脉冲驱动模块
|
||||
// 文件名称:bsp_step_moto
|
||||
// 版本名称:V1.0
|
||||
// 文件说明:控制电机转动脉冲输出文件
|
||||
// 日期时间:2018年8月23日20点37分
|
||||
// 文件作者:Jackie Chan
|
||||
// 修改记录:
|
||||
// 版本号 日期 作者 说明
|
||||
// V1.0 2018.08.23 J.C 正式发布
|
||||
//
|
||||
// 公司名称:多场低温科技有限公司
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#include "bsp.h"
|
||||
|
||||
// 定义GPIO端口
|
||||
#define GPIO_PORT_STEP GPIOC // 脉冲输入,内部下拉,上升沿触发
|
||||
#define GPIO_PIN_STEP GPIO_Pin_7
|
||||
#define MOTO_STEP_0() GPIO_PORT_STEP->BRR = GPIO_PIN_STEP
|
||||
#define MOTO_STEP_1() GPIO_PORT_STEP->BSRR = GPIO_PIN_STEP
|
||||
|
||||
// PA6 零位信号输出引脚
|
||||
#define GPIO_PORT_ZERO_SIG GPIOA
|
||||
#define GPIO_PIN_ZERO_SIG GPIO_Pin_6
|
||||
#define ZERO_SIG_TOGGLE() (GPIO_PORT_ZERO_SIG->ODR ^= GPIO_PIN_ZERO_SIG)
|
||||
|
||||
extern DIGITIAL_TUBE_T g_tTube;
|
||||
MOTO_T g_tMoto;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// 函 数 名: bsp_InitStepMoto
|
||||
// 功能说明: 配置步进电器驱动IO
|
||||
// 形 参: 无
|
||||
// 返 回 值: 无
|
||||
//------------------------------------------------------------------------------
|
||||
void bsp_InitStepMoto(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
// 初始化 PA6 为零位信号输出引脚
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_ZERO_SIG;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||||
GPIO_Init(GPIO_PORT_ZERO_SIG, &GPIO_InitStructure);
|
||||
GPIO_PORT_ZERO_SIG->BRR = GPIO_PIN_ZERO_SIG; // 默认输出低电平
|
||||
|
||||
g_tMoto.Dir = 0;
|
||||
g_tMoto.StepFreq = 0;
|
||||
g_tMoto.StepCount = 0;
|
||||
g_tMoto.Running = 0;
|
||||
g_tMoto.Pos = 0;
|
||||
g_tMoto.pv_pulse = 0;
|
||||
g_tMoto.sv_pulse = 0;
|
||||
g_tMoto.prev_pv_pulse = 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// 函 数 名: MOTO_StartWork
|
||||
// 功能说明: 控制电机开始旋转
|
||||
// 形 参: _speed 旋转速度. 换相的频率。Hz
|
||||
// _dir 旋转方向 0 表示正转, 1表示反转
|
||||
// _step 旋转步数 0 表示一直旋转
|
||||
// 返 回 值: 无
|
||||
//------------------------------------------------------------------------------
|
||||
void MOTO_Start(uint32_t _speed, uint8_t _dir, int32_t _stpes)
|
||||
{
|
||||
bsp_drv8880_enable_config(ENABLE);
|
||||
g_tMoto.Dir = _dir;
|
||||
g_tMoto.StepFreq = _speed;
|
||||
g_tMoto.StepCount = _stpes;
|
||||
g_tMoto.AllStep = _stpes;
|
||||
g_tMoto.CurrentStep = 0;
|
||||
g_tMoto.Running = 1;
|
||||
|
||||
// void bsp_SetTIMforInt(TIM_TypeDef* TIMx, uint32_t _ulFreq, uint8_t _PreemptionPriority, uint8_t _SubPriority)
|
||||
// bsp_SetTIMforInt(TIM6, _speed*2, 2, 2);
|
||||
switch (_dir)
|
||||
{
|
||||
case 1:
|
||||
bsp_drv8880_config_dir(DIR_CW);
|
||||
break;
|
||||
case 0:
|
||||
bsp_drv8880_config_dir(DIR_CCW);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
bsp_SetTIMforInt(TIM6, _speed * 2, 0, 0);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// 函 数 名: MOTO_ShangeSpeed
|
||||
// 功能说明: 控制电机的步进速度
|
||||
// 形 参: _speed 旋转速度. 换相的频率。Hz
|
||||
// _dir 旋转方向 0 表示正转, 1表示反转
|
||||
// _step 旋转步数 0 表示一直旋转
|
||||
// 返 回 值: 无
|
||||
//------------------------------------------------------------------------------
|
||||
void MOTO_ShangeSpeed(uint32_t _speed)
|
||||
{
|
||||
g_tMoto.StepFreq = _speed;
|
||||
|
||||
if (g_tMoto.Running == 1)
|
||||
{
|
||||
// void bsp_SetTIMforInt(TIM_TypeDef* TIMx, uint32_t _ulFreq, uint8_t _PreemptionPriority, uint8_t _SubPriority)
|
||||
bsp_SetTIMforInt(TIM6, _speed, 2, 2);
|
||||
}
|
||||
}
|
||||
|
||||
void MOTO_ZorePos(void)
|
||||
{
|
||||
MOTO_Stop();
|
||||
g_tMoto.sv_pulse = 0;
|
||||
g_tMoto.pv_pulse = 0;
|
||||
g_tMoto.prev_pv_pulse = 0;
|
||||
GPIO_PORT_ZERO_SIG->BRR = GPIO_PIN_ZERO_SIG; // 归零时 PA6 输出低
|
||||
BEEP_Start(1500, 5, 5, 3);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// 函 数 名: MOTO_Stop
|
||||
// 功能说明: 控制电机停止运行。
|
||||
// 形 参: 无
|
||||
// 返 回 值: 无
|
||||
//------------------------------------------------------------------------------
|
||||
void MOTO_Stop(void)
|
||||
{
|
||||
// void bsp_SetTIMforInt(TIM_TypeDef* TIMx, uint32_t _ulFreq, uint8_t _PreemptionPriority, uint8_t _SubPriority)
|
||||
bsp_SetTIMforInt(TIM6, 0, 0, 0);
|
||||
g_tMoto.Running = 0;
|
||||
|
||||
MOTO_STEP_0();
|
||||
// bsp_drv8880_enable_config(DISABLE);
|
||||
if (g_tTube.state == SEARCH)
|
||||
{
|
||||
g_tTube.state = IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// 函 数 名: MOTO_Pause
|
||||
// 功能说明: 控制电机暂停旋转。
|
||||
// 形 参: 无
|
||||
// 返 回 值: 无
|
||||
//------------------------------------------------------------------------------
|
||||
void MOTO_Pause(void)
|
||||
{
|
||||
// void bsp_SetTIMforInt(TIM_TypeDef* TIMx, uint32_t _ulFreq, uint8_t _PreemptionPriority, uint8_t _SubPriority)
|
||||
bsp_SetTIMforInt(TIM6, 0, 0, 0);
|
||||
g_tMoto.Running = 0;
|
||||
MOTO_STEP_0();
|
||||
// bsp_drv8880_enable_config(DISABLE);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// 函 数 名: MOTO_RoudToStep
|
||||
// 功能说明: 圈数换算为步数。28BYJ48 电机步距角度 = 5.625/64度.
|
||||
// 形 参: 无
|
||||
// 返 回 值: 无
|
||||
//------------------------------------------------------------------------------
|
||||
uint32_t MOTO_RoudToStep(void)
|
||||
{
|
||||
uint32_t steps;
|
||||
|
||||
/* 28BYJ48 电机步距角度 = 5.625/64度.
|
||||
一圈 360度;
|
||||
step = 360 / (5.625 / 64)
|
||||
*/
|
||||
steps = (360 * 64 * 1000 / 4) / 5625; // 4096步
|
||||
|
||||
return steps;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// 函 数 名: MOTO_ISR
|
||||
// 功能说明: 中断服务程序
|
||||
// 形 参: 无
|
||||
// 返 回 值: 无
|
||||
//------------------------------------------------------------------------------
|
||||
void MOTO_ISR(void)
|
||||
{
|
||||
if (g_tMoto.Running == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// BEEP_KeyTone();
|
||||
|
||||
// g_tMoto.Pos = 0;
|
||||
switch (g_tMoto.Pos)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
g_tMoto.Pos = 1;
|
||||
MOTO_STEP_1();
|
||||
g_tMoto.prev_pv_pulse = g_tMoto.pv_pulse;
|
||||
if (g_tMoto.pv_pulse < g_tMoto.sv_pulse)
|
||||
{
|
||||
g_tMoto.pv_pulse++;
|
||||
}
|
||||
else if (g_tMoto.pv_pulse > g_tMoto.sv_pulse)
|
||||
{
|
||||
g_tMoto.pv_pulse--;
|
||||
}
|
||||
// 检测过零点:pv_pulse 每跨越一个 STEP_PER_LAP(即每转一圈)翻转PA6
|
||||
if ((g_tMoto.prev_pv_pulse / STEP_PER_LAP) != (g_tMoto.pv_pulse / STEP_PER_LAP))
|
||||
{
|
||||
ZERO_SIG_TOGGLE();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 1:
|
||||
{
|
||||
g_tMoto.Pos = 0;
|
||||
MOTO_STEP_0();
|
||||
g_tMoto.CurrentStep++;
|
||||
if (g_tMoto.pv_pulse == g_tMoto.sv_pulse)
|
||||
{
|
||||
MOTO_Stop();
|
||||
TIM_ClearITPendingBit(TIM6, TIM_IT_Update); /* 清除中断标志位 */
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// 函 数 名: TIM6_IRQHandler
|
||||
// 功能说明: 外部中断服务程序.
|
||||
// 形 参:无
|
||||
// 返 回 值: 无
|
||||
//------------------------------------------------------------------------------
|
||||
#ifndef TIM6_ISR_MOVE_OUT /* bsp.h 中定义此行,表示本函数移到 stam32fxxx_it.c。 避免重复定义 */
|
||||
void TIM6_IRQHandler(void)
|
||||
{
|
||||
if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET)
|
||||
{
|
||||
MOTO_ISR(); /* 中断服务程序 */
|
||||
|
||||
TIM_ClearITPendingBit(TIM6, TIM_IT_Update); /* 清除中断标志位 */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//-------------------------------- End of file ---------------------------------
|
||||
671
User/bsp/src/bsp_tim_pwm.c
Normal file
671
User/bsp/src/bsp_tim_pwm.c
Normal file
@@ -0,0 +1,671 @@
|
||||
/*
|
||||
* @Author: Memory 1619005172@qq.com
|
||||
* @Date: 2026-04-15 18:01:19
|
||||
* @LastEditors: Memory 1619005172@qq.com
|
||||
* @LastEditTime: 2026-04-15 18:58:21
|
||||
* @FilePath: \MDK-ARMd:\Project\MFT\Motor\User\bsp\src\bsp_tim_pwm.c
|
||||
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
||||
*/
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
*
|
||||
* 模块名称 : TIM基本定时中断和PWM驱动模块
|
||||
* 文件名称 : bsp_tim_pwm.c
|
||||
* 版 本 : V1.1
|
||||
* 说 明 : 利用STM32F4内部TIM输出PWM信号, 并实现基本的定时中断
|
||||
* 修改记录 :
|
||||
* 版本号 日期 作者 说明
|
||||
* V1.0 2013-08-16 armfly 正式发布
|
||||
* V1.1 2014-06-15 armfly 完善 bsp_SetTIMOutPWM,当占空比=0和100%时,关闭定时器,GPIO配置为输出
|
||||
* V1.2 2015-05-08 armfly 解决TIM8不能输出PWM的问题。
|
||||
* V1.3 2015-07-30 armfly 增加反相引脚输出PWM函数 bsp_SetTIMOutPWM_N();
|
||||
*
|
||||
* Copyright (C), 2015-2016, 安富莱电子 www.armfly.com
|
||||
*
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#include "bsp.h"
|
||||
|
||||
/*
|
||||
可以输出到GPIO的TIM通道:
|
||||
|
||||
PA0 TIM5_CH1
|
||||
PA0 TIM5_CH2 TIM2_CH2
|
||||
PA2 TIM5_CH3 TIM2_CH3
|
||||
PA3 TIM5_CH4 TIM2_CH4
|
||||
|
||||
PA6 TIM3_CH1
|
||||
PA7 TIM3_CH2
|
||||
|
||||
PB0 TIM3_CH3
|
||||
PB1 TIM3_CH4
|
||||
|
||||
PE9 TIM1_CH1
|
||||
PE11 TIM1_CH2
|
||||
PE13 TIM1_CH3
|
||||
|
||||
PE14 TIM1_CH4
|
||||
|
||||
PD12 TIM4_CH1
|
||||
PD13 TIM4_CH2
|
||||
PD14 TIM4_CH3
|
||||
PD15 TIM4_CH4
|
||||
|
||||
PC6 TIM8_CH1
|
||||
PC7 TIM8_CH2
|
||||
PC8 TIM8_CH3
|
||||
PC9 TIM8_CH4
|
||||
|
||||
PA8 TIM1_CH1
|
||||
PA9 TIM1_CH2
|
||||
PA10 TIM1_CH3
|
||||
PA11 TIM1_CH4
|
||||
|
||||
PB3 TIM2_CH2
|
||||
PB4 TIM3_CH1
|
||||
PB5 TIM3_CH2
|
||||
|
||||
PB6 TIM4_CH1
|
||||
PB7 TIM4_CH2
|
||||
PB8 TIM4_CH3
|
||||
PB9 TIM4_CH4
|
||||
|
||||
APB1 定时器有 TIM2, TIM3 ,TIM4, TIM5, TIM6, TIM7 --- 36M
|
||||
APB2 定时器有 TIM1, TIM8 ---- 72M
|
||||
*/
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_GetRCCofGPIO
|
||||
* 功能说明: 根据GPIO 得到RCC寄存器
|
||||
* 形 参:无
|
||||
* 返 回 值: GPIO外设时钟名
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
uint32_t bsp_GetRCCofGPIO(GPIO_TypeDef *GPIOx)
|
||||
{
|
||||
uint32_t rcc = 0;
|
||||
|
||||
if (GPIOx == GPIOA)
|
||||
{
|
||||
rcc = RCC_APB2Periph_GPIOA;
|
||||
}
|
||||
else if (GPIOx == GPIOB)
|
||||
{
|
||||
rcc = RCC_APB2Periph_GPIOB;
|
||||
}
|
||||
else if (GPIOx == GPIOC)
|
||||
{
|
||||
rcc = RCC_APB2Periph_GPIOC;
|
||||
}
|
||||
else if (GPIOx == GPIOD)
|
||||
{
|
||||
rcc = RCC_APB2Periph_GPIOD;
|
||||
}
|
||||
else if (GPIOx == GPIOE)
|
||||
{
|
||||
rcc = RCC_APB2Periph_GPIOE;
|
||||
}
|
||||
else if (GPIOx == GPIOF)
|
||||
{
|
||||
rcc = RCC_APB2Periph_GPIOF;
|
||||
}
|
||||
else if (GPIOx == GPIOG)
|
||||
{
|
||||
rcc = RCC_APB2Periph_GPIOG;
|
||||
}
|
||||
|
||||
return rcc;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_GetRCCofTIM
|
||||
* 功能说明: 根据TIM 得到RCC寄存器
|
||||
* 形 参:无
|
||||
* 返 回 值: TIM外设时钟名
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
uint32_t bsp_GetRCCofTIM(TIM_TypeDef *TIMx)
|
||||
{
|
||||
uint32_t rcc = 0;
|
||||
|
||||
/*
|
||||
APB1 定时器有 TIM2, TIM3 ,TIM4, TIM5, TIM6, TIM7, TIM12, TIM13, TIM14
|
||||
APB2 定时器有 TIM1, TIM8 ,TIM9, TIM10, TIM11
|
||||
*/
|
||||
if (TIMx == TIM1)
|
||||
{
|
||||
rcc = RCC_APB2Periph_TIM1;
|
||||
}
|
||||
else if (TIMx == TIM8)
|
||||
{
|
||||
rcc = RCC_APB2Periph_TIM8;
|
||||
}
|
||||
else if (TIMx == TIM9)
|
||||
{
|
||||
rcc = RCC_APB2Periph_TIM9;
|
||||
}
|
||||
else if (TIMx == TIM10)
|
||||
{
|
||||
rcc = RCC_APB2Periph_TIM10;
|
||||
}
|
||||
else if (TIMx == TIM11)
|
||||
{
|
||||
rcc = RCC_APB2Periph_TIM11;
|
||||
}
|
||||
/* 下面是 APB1时钟 */
|
||||
else if (TIMx == TIM2)
|
||||
{
|
||||
rcc = RCC_APB1Periph_TIM2;
|
||||
}
|
||||
else if (TIMx == TIM3)
|
||||
{
|
||||
rcc = RCC_APB1Periph_TIM3;
|
||||
}
|
||||
else if (TIMx == TIM4)
|
||||
{
|
||||
rcc = RCC_APB1Periph_TIM4;
|
||||
}
|
||||
else if (TIMx == TIM5)
|
||||
{
|
||||
rcc = RCC_APB1Periph_TIM5;
|
||||
}
|
||||
else if (TIMx == TIM6)
|
||||
{
|
||||
rcc = RCC_APB1Periph_TIM6;
|
||||
}
|
||||
else if (TIMx == TIM7)
|
||||
{
|
||||
rcc = RCC_APB1Periph_TIM7;
|
||||
}
|
||||
else if (TIMx == TIM12)
|
||||
{
|
||||
rcc = RCC_APB1Periph_TIM12;
|
||||
}
|
||||
else if (TIMx == TIM13)
|
||||
{
|
||||
rcc = RCC_APB1Periph_TIM13;
|
||||
}
|
||||
else if (TIMx == TIM14)
|
||||
{
|
||||
rcc = RCC_APB1Periph_TIM14;
|
||||
}
|
||||
|
||||
return rcc;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_ConfigTimGpio
|
||||
* 功能说明: 配置GPIO和TIM时钟, GPIO连接到TIM输出通道
|
||||
* 形 参: GPIOx
|
||||
* GPIO_PinX
|
||||
* TIMx
|
||||
* _ucChannel
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void bsp_ConfigTimGpio(GPIO_TypeDef *GPIOx, uint16_t GPIO_PinX, TIM_TypeDef *TIMx, uint8_t _ucChannel)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
/* 使能GPIO时钟 */
|
||||
RCC_APB2PeriphClockCmd(bsp_GetRCCofGPIO(GPIOx), ENABLE);
|
||||
|
||||
/* 使能TIM时钟 */
|
||||
if ((TIMx == TIM1) || (TIMx == TIM8))
|
||||
{
|
||||
RCC_APB2PeriphClockCmd(bsp_GetRCCofTIM(TIMx), ENABLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
RCC_APB1PeriphClockCmd(bsp_GetRCCofTIM(TIMx), ENABLE);
|
||||
}
|
||||
|
||||
/* 配置GPIO */
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PinX;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; /* 复用功能 */
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||||
GPIO_Init(GPIOx, &GPIO_InitStructure);
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_ConfigGpioOut
|
||||
* 功能说明: 配置GPIO为推挽输出。主要用于PWM输出,占空比为0和100的情况。
|
||||
* 形 参: GPIOx
|
||||
* GPIO_PinX
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void bsp_ConfigGpioOut(GPIO_TypeDef *GPIOx, uint16_t GPIO_PinX)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
/* 使能GPIO时钟 */
|
||||
RCC_APB2PeriphClockCmd(bsp_GetRCCofGPIO(GPIOx), ENABLE);
|
||||
|
||||
/* 配置GPIO */
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_PinX; /* 带入的形参 */
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; /* 输出 */
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||||
GPIO_Init(GPIOx, &GPIO_InitStructure);
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_SetTIMOutPWM
|
||||
* 功能说明: 设置引脚输出的PWM信号的频率和占空比. 当频率为0,并且占空为0时,关闭定时器,GPIO输出0;
|
||||
* 当频率为0,占空比为100%时,GPIO输出1.
|
||||
* 形 参: _ulFreq : PWM信号频率,单位Hz (实际测试,最大输出频率为 168M / 4 = 42M). 0 表示禁止输出
|
||||
* _ulDutyCycle : PWM信号占空比,单位:万分之一。如5000,表示50.00%的占空比
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void bsp_SetTIMOutPWM(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, TIM_TypeDef *TIMx, uint8_t _ucChannel,
|
||||
uint32_t _ulFreq, uint32_t _ulDutyCycle)
|
||||
{
|
||||
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
|
||||
TIM_OCInitTypeDef TIM_OCInitStructure;
|
||||
uint16_t usPeriod;
|
||||
uint16_t usPrescaler;
|
||||
uint32_t uiTIMxCLK;
|
||||
|
||||
if (_ulDutyCycle == 0)
|
||||
{
|
||||
TIM_Cmd(TIMx, DISABLE); /* 关闭PWM输出 */
|
||||
bsp_ConfigGpioOut(GPIOx, GPIO_Pin); /* 配置GPIO为推挽输出 */
|
||||
GPIO_WriteBit(GPIOx, GPIO_Pin, Bit_RESET); /* PWM = 0 */
|
||||
return;
|
||||
}
|
||||
else if (_ulDutyCycle == 10000)
|
||||
{
|
||||
TIM_Cmd(TIMx, DISABLE); /* 关闭PWM输出 */
|
||||
|
||||
bsp_ConfigGpioOut(GPIOx, GPIO_Pin); /* 配置GPIO为推挽输出 */
|
||||
GPIO_WriteBit(GPIOx, GPIO_Pin, Bit_SET); /* PWM = 1 */
|
||||
return;
|
||||
}
|
||||
|
||||
bsp_ConfigTimGpio(GPIOx, GPIO_Pin, TIMx, _ucChannel); /* 使能GPIO和TIM时钟,并连接TIM通道到GPIO */
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
system_stm32f4xx.c 文件中 void SetSysClock(void) 函数对时钟的配置如下:
|
||||
|
||||
HCLK = SYSCLK / 1 (AHB1Periph)
|
||||
PCLK2 = HCLK / 2 (APB2Periph)
|
||||
PCLK1 = HCLK / 4 (APB1Periph)
|
||||
|
||||
因为APB1 prescaler != 1, 所以 APB1上的TIMxCLK = PCLK1 x 2 = SystemCoreClock / 2;
|
||||
因为APB2 prescaler != 1, 所以 APB2上的TIMxCLK = PCLK2 x 2 = SystemCoreClock;
|
||||
|
||||
APB1 定时器有 TIM2, TIM3 ,TIM4, TIM5, TIM6, TIM6, TIM12, TIM13,TIM14
|
||||
APB2 定时器有 TIM1, TIM8 ,TIM9, TIM10, TIM11
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
if ((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM9) || (TIMx == TIM10) || (TIMx == TIM11))
|
||||
{
|
||||
/* APB2 定时器 */
|
||||
uiTIMxCLK = SystemCoreClock;
|
||||
}
|
||||
else /* APB1 定时器 */
|
||||
{
|
||||
uiTIMxCLK = SystemCoreClock; // SystemCoreClock / 2;
|
||||
}
|
||||
|
||||
if (_ulFreq < 100)
|
||||
{
|
||||
usPrescaler = 10000 - 1; /* 分频比 = 10000 */
|
||||
usPeriod = (uiTIMxCLK / 10000) / _ulFreq - 1; /* 自动重装的值 */
|
||||
}
|
||||
else if (_ulFreq < 3000)
|
||||
{
|
||||
usPrescaler = 100 - 1; /* 分频比 = 100 */
|
||||
usPeriod = (uiTIMxCLK / 100) / _ulFreq - 1; /* 自动重装的值 */
|
||||
}
|
||||
else /* 大于4K的频率,无需分频 */
|
||||
{
|
||||
usPrescaler = 0; /* 分频比 = 1 */
|
||||
usPeriod = uiTIMxCLK / _ulFreq - 1; /* 自动重装的值 */
|
||||
}
|
||||
|
||||
/* Time base configuration */
|
||||
TIM_TimeBaseStructure.TIM_Period = usPeriod;
|
||||
TIM_TimeBaseStructure.TIM_Prescaler = usPrescaler;
|
||||
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
|
||||
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
|
||||
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
|
||||
TIM_TimeBaseInit(TIMx, &TIM_TimeBaseStructure);
|
||||
|
||||
/* PWM1 Mode configuration: Channel1 */
|
||||
TIM_OCStructInit(&TIM_OCInitStructure); /* 初始化结构体成员 */
|
||||
|
||||
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
|
||||
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
|
||||
TIM_OCInitStructure.TIM_Pulse = (_ulDutyCycle * usPeriod) / 10000;
|
||||
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
|
||||
|
||||
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable; /* only for TIM1 and TIM8. */
|
||||
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; /* only for TIM1 and TIM8. */
|
||||
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; /* only for TIM1 and TIM8. */
|
||||
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset; /* only for TIM1 and TIM8. */
|
||||
|
||||
if (_ucChannel == 1)
|
||||
{
|
||||
TIM_OC1Init(TIMx, &TIM_OCInitStructure);
|
||||
TIM_OC1PreloadConfig(TIMx, TIM_OCPreload_Enable);
|
||||
}
|
||||
else if (_ucChannel == 2)
|
||||
{
|
||||
TIM_OC2Init(TIMx, &TIM_OCInitStructure);
|
||||
TIM_OC2PreloadConfig(TIMx, TIM_OCPreload_Enable);
|
||||
}
|
||||
else if (_ucChannel == 3)
|
||||
{
|
||||
TIM_OC3Init(TIMx, &TIM_OCInitStructure);
|
||||
TIM_OC3PreloadConfig(TIMx, TIM_OCPreload_Enable);
|
||||
}
|
||||
else if (_ucChannel == 4)
|
||||
{
|
||||
TIM_OC4Init(TIMx, &TIM_OCInitStructure);
|
||||
TIM_OC4PreloadConfig(TIMx, TIM_OCPreload_Enable);
|
||||
}
|
||||
|
||||
TIM_ARRPreloadConfig(TIMx, ENABLE);
|
||||
|
||||
/* TIMx enable counter */
|
||||
TIM_Cmd(TIMx, ENABLE);
|
||||
|
||||
/* 下面这句话对于TIM1和TIM8是必须的,对于TIM2-TIM6则不必要 */
|
||||
if ((TIMx == TIM1) || (TIMx == TIM8))
|
||||
{
|
||||
TIM_CtrlPWMOutputs(TIMx, ENABLE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_SetTIMOutPWM_N
|
||||
* 功能说明: 设置TIM8_CH1N 等反相引脚输出的PWM信号的频率和占空比. 当频率为0,并且占空为0时,关闭定时器,GPIO输出0;
|
||||
* 当频率为0,占空比为100%时,GPIO输出1.
|
||||
* 形 参: _ulFreq : PWM信号频率,单位Hz (实际测试,最大输出频率为 168M / 4 = 42M). 0 表示禁止输出
|
||||
* _ulDutyCycle : PWM信号占空比,单位:万分之一。如5000,表示50.00%的占空比
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void bsp_SetTIMOutPWM_N(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, TIM_TypeDef *TIMx, uint8_t _ucChannel,
|
||||
uint32_t _ulFreq, uint32_t _ulDutyCycle)
|
||||
{
|
||||
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
|
||||
TIM_OCInitTypeDef TIM_OCInitStructure;
|
||||
uint16_t usPeriod;
|
||||
uint16_t usPrescaler;
|
||||
uint32_t uiTIMxCLK;
|
||||
|
||||
if (_ulDutyCycle == 0)
|
||||
{
|
||||
TIM_Cmd(TIMx, DISABLE); /* 关闭PWM输出 */
|
||||
bsp_ConfigGpioOut(GPIOx, GPIO_Pin); /* 配置GPIO为推挽输出 */
|
||||
GPIO_WriteBit(GPIOx, GPIO_Pin, Bit_RESET); /* PWM = 0 */
|
||||
return;
|
||||
}
|
||||
else if (_ulDutyCycle == 10000)
|
||||
{
|
||||
TIM_Cmd(TIMx, DISABLE); /* 关闭PWM输出 */
|
||||
|
||||
bsp_ConfigGpioOut(GPIOx, GPIO_Pin); /* 配置GPIO为推挽输出 */
|
||||
GPIO_WriteBit(GPIOx, GPIO_Pin, Bit_SET); /* PWM = 1 */
|
||||
return;
|
||||
}
|
||||
|
||||
bsp_ConfigTimGpio(GPIOx, GPIO_Pin, TIMx, _ucChannel); /* 使能GPIO和TIM时钟,并连接TIM通道到GPIO */
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
system_stm32f4xx.c 文件中 void SetSysClock(void) 函数对时钟的配置如下:
|
||||
|
||||
HCLK = SYSCLK / 1 (AHB1Periph)
|
||||
PCLK2 = HCLK / 2 (APB2Periph)
|
||||
PCLK1 = HCLK / 4 (APB1Periph)
|
||||
|
||||
因为APB1 prescaler != 1, 所以 APB1上的TIMxCLK = PCLK1 x 2 = SystemCoreClock / 2;
|
||||
因为APB2 prescaler != 1, 所以 APB2上的TIMxCLK = PCLK2 x 2 = SystemCoreClock;
|
||||
|
||||
APB1 定时器有 TIM2, TIM3 ,TIM4, TIM5, TIM6, TIM6, TIM12, TIM13,TIM14
|
||||
APB2 定时器有 TIM1, TIM8 ,TIM9, TIM10, TIM11
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
if ((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM9) || (TIMx == TIM10) || (TIMx == TIM11))
|
||||
{
|
||||
/* APB2 定时器 */
|
||||
uiTIMxCLK = SystemCoreClock;
|
||||
}
|
||||
else /* APB1 定时器 */
|
||||
{
|
||||
uiTIMxCLK = SystemCoreClock; // SystemCoreClock / 2;
|
||||
}
|
||||
|
||||
if (_ulFreq < 100)
|
||||
{
|
||||
usPrescaler = 10000 - 1; /* 分频比 = 10000 */
|
||||
usPeriod = (uiTIMxCLK / 10000) / _ulFreq - 1; /* 自动重装的值 */
|
||||
}
|
||||
else if (_ulFreq < 3000)
|
||||
{
|
||||
usPrescaler = 100 - 1; /* 分频比 = 100 */
|
||||
usPeriod = (uiTIMxCLK / 100) / _ulFreq - 1; /* 自动重装的值 */
|
||||
}
|
||||
else /* 大于4K的频率,无需分频 */
|
||||
{
|
||||
usPrescaler = 0; /* 分频比 = 1 */
|
||||
usPeriod = uiTIMxCLK / _ulFreq - 1; /* 自动重装的值 */
|
||||
}
|
||||
|
||||
/* Time base configuration */
|
||||
TIM_TimeBaseStructure.TIM_Period = usPeriod;
|
||||
TIM_TimeBaseStructure.TIM_Prescaler = usPrescaler;
|
||||
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
|
||||
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
|
||||
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
|
||||
TIM_TimeBaseInit(TIMx, &TIM_TimeBaseStructure);
|
||||
|
||||
/* PWM1 Mode configuration: Channel1 */
|
||||
TIM_OCStructInit(&TIM_OCInitStructure); /* 初始化结构体成员 */
|
||||
|
||||
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
|
||||
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable; /* 和 bsp_SetTIMOutPWM_N() 不同 */
|
||||
TIM_OCInitStructure.TIM_Pulse = (_ulDutyCycle * usPeriod) / 10000;
|
||||
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
|
||||
|
||||
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; /* only for TIM1 and TIM8. */
|
||||
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; /* only for TIM1 and TIM8. */
|
||||
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; /* only for TIM1 and TIM8. */
|
||||
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset; /* only for TIM1 and TIM8. */
|
||||
|
||||
if (_ucChannel == 1)
|
||||
{
|
||||
TIM_OC1Init(TIMx, &TIM_OCInitStructure);
|
||||
TIM_OC1PreloadConfig(TIMx, TIM_OCPreload_Enable);
|
||||
}
|
||||
else if (_ucChannel == 2)
|
||||
{
|
||||
TIM_OC2Init(TIMx, &TIM_OCInitStructure);
|
||||
TIM_OC2PreloadConfig(TIMx, TIM_OCPreload_Enable);
|
||||
}
|
||||
else if (_ucChannel == 3)
|
||||
{
|
||||
TIM_OC3Init(TIMx, &TIM_OCInitStructure);
|
||||
TIM_OC3PreloadConfig(TIMx, TIM_OCPreload_Enable);
|
||||
}
|
||||
else if (_ucChannel == 4)
|
||||
{
|
||||
TIM_OC4Init(TIMx, &TIM_OCInitStructure);
|
||||
TIM_OC4PreloadConfig(TIMx, TIM_OCPreload_Enable);
|
||||
}
|
||||
|
||||
TIM_ARRPreloadConfig(TIMx, ENABLE);
|
||||
|
||||
/* TIMx enable counter */
|
||||
TIM_Cmd(TIMx, ENABLE);
|
||||
|
||||
/* 下面这句话对于TIM1和TIM8是必须的,对于TIM2-TIM6则不必要 */
|
||||
if ((TIMx == TIM1) || (TIMx == TIM8))
|
||||
{
|
||||
TIM_CtrlPWMOutputs(TIMx, ENABLE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_SetTIMforInt
|
||||
* 功能说明: 配置TIM和NVIC,用于简单的定时中断. 开启定时中断。 中断服务程序由应用程序实现。
|
||||
* 形 参: TIMx : 定时器
|
||||
* _ulFreq : 定时频率 (Hz)。 0 表示关闭。
|
||||
* _PreemptionPriority : 中断优先级分组
|
||||
* _SubPriority : 子优先级
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void bsp_SetTIMforInt(TIM_TypeDef *TIMx, uint32_t _ulFreq, uint8_t _PreemptionPriority, uint8_t _SubPriority)
|
||||
{
|
||||
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
|
||||
uint16_t usPeriod;
|
||||
uint16_t usPrescaler;
|
||||
uint32_t uiTIMxCLK;
|
||||
|
||||
/* 使能TIM时钟 */
|
||||
if ((TIMx == TIM1) || (TIMx == TIM8))
|
||||
{
|
||||
RCC_APB2PeriphClockCmd(bsp_GetRCCofTIM(TIMx), ENABLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
RCC_APB1PeriphClockCmd(bsp_GetRCCofTIM(TIMx), ENABLE);
|
||||
}
|
||||
|
||||
if (_ulFreq == 0)
|
||||
{
|
||||
TIM_Cmd(TIMx, DISABLE); /* 关闭定时输出 */
|
||||
|
||||
/* 关闭TIM定时更新中断 (Update) */
|
||||
{
|
||||
NVIC_InitTypeDef NVIC_InitStructure; /* 中断结构体在 misc.h 中定义 */
|
||||
uint8_t irq = 0; /* 中断号, 定义在 stm32f4xx.h */
|
||||
|
||||
if (TIMx == TIM1)
|
||||
irq = TIM1_UP_IRQn;
|
||||
else if (TIMx == TIM2)
|
||||
irq = TIM2_IRQn;
|
||||
else if (TIMx == TIM3)
|
||||
irq = TIM3_IRQn;
|
||||
else if (TIMx == TIM4)
|
||||
irq = TIM4_IRQn;
|
||||
else if (TIMx == TIM5)
|
||||
irq = TIM5_IRQn;
|
||||
else if (TIMx == TIM6)
|
||||
irq = TIM6_IRQn;
|
||||
else if (TIMx == TIM7)
|
||||
irq = TIM7_IRQn;
|
||||
else if (TIMx == TIM8)
|
||||
irq = TIM8_UP_IRQn;
|
||||
|
||||
NVIC_InitStructure.NVIC_IRQChannel = irq;
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = _PreemptionPriority;
|
||||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = _SubPriority;
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;
|
||||
NVIC_Init(&NVIC_InitStructure);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
system_stm32f4xx.c 文件中 static void SetSysClockToHSE(void) 函数对时钟的配置如下:
|
||||
|
||||
//HCLK = SYSCLK
|
||||
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
|
||||
|
||||
//PCLK2 = HCLK
|
||||
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
|
||||
|
||||
//PCLK1 = HCLK
|
||||
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1;
|
||||
|
||||
APB1 定时器有 TIM2, TIM3 ,TIM4, TIM5, TIM6, TIM7, TIM12, TIM13,TIM14
|
||||
APB2 定时器有 TIM1, TIM8 ,TIM9, TIM10, TIM11
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
if ((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM9) || (TIMx == TIM10) || (TIMx == TIM11))
|
||||
{
|
||||
/* APB2 定时器 */
|
||||
uiTIMxCLK = SystemCoreClock;
|
||||
}
|
||||
else /* APB1 定时器 . */
|
||||
{
|
||||
uiTIMxCLK = SystemCoreClock; // SystemCoreClock / 2;
|
||||
}
|
||||
|
||||
if (_ulFreq < 100)
|
||||
{
|
||||
usPrescaler = 10000 - 1; /* 分频比 = 1000 */
|
||||
usPeriod = (uiTIMxCLK / 10000) / _ulFreq - 1; /* 自动重装的值 */
|
||||
}
|
||||
else if (_ulFreq < 3000)
|
||||
{
|
||||
usPrescaler = 100 - 1; /* 分频比 = 100 */
|
||||
usPeriod = (uiTIMxCLK / 100) / _ulFreq - 1; /* 自动重装的值 */
|
||||
}
|
||||
else /* 大于4K的频率,无需分频 */
|
||||
{
|
||||
usPrescaler = 0; /* 分频比 = 1 */
|
||||
usPeriod = uiTIMxCLK / _ulFreq - 1; /* 自动重装的值 */
|
||||
}
|
||||
|
||||
/* Time base configuration */
|
||||
TIM_TimeBaseStructure.TIM_Period = usPeriod;
|
||||
TIM_TimeBaseStructure.TIM_Prescaler = usPrescaler;
|
||||
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
|
||||
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
|
||||
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
|
||||
|
||||
TIM_TimeBaseInit(TIMx, &TIM_TimeBaseStructure);
|
||||
|
||||
TIM_ARRPreloadConfig(TIMx, ENABLE);
|
||||
|
||||
/* TIM Interrupts enable */
|
||||
TIM_ITConfig(TIMx, TIM_IT_Update, ENABLE);
|
||||
|
||||
/* TIMx enable counter */
|
||||
TIM_Cmd(TIMx, ENABLE);
|
||||
|
||||
/* 配置TIM定时更新中断 (Update) */
|
||||
{
|
||||
NVIC_InitTypeDef NVIC_InitStructure; /* 中断结构体在 misc.h 中定义 */
|
||||
uint8_t irq = 0; /* 中断号, 定义在 stm32f4xx.h */
|
||||
|
||||
if (TIMx == TIM1)
|
||||
irq = TIM1_UP_IRQn;
|
||||
else if (TIMx == TIM2)
|
||||
irq = TIM2_IRQn;
|
||||
else if (TIMx == TIM3)
|
||||
irq = TIM3_IRQn;
|
||||
else if (TIMx == TIM4)
|
||||
irq = TIM4_IRQn;
|
||||
else if (TIMx == TIM5)
|
||||
irq = TIM5_IRQn;
|
||||
else if (TIMx == TIM6)
|
||||
irq = TIM6_IRQn;
|
||||
else if (TIMx == TIM7)
|
||||
irq = TIM7_IRQn;
|
||||
else if (TIMx == TIM8)
|
||||
irq = TIM8_UP_IRQn;
|
||||
|
||||
NVIC_InitStructure.NVIC_IRQChannel = irq;
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = _PreemptionPriority;
|
||||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = _SubPriority;
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_Init(&NVIC_InitStructure);
|
||||
}
|
||||
}
|
||||
|
||||
/***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
|
||||
673
User/bsp/src/bsp_timer.c
Normal file
673
User/bsp/src/bsp_timer.c
Normal file
@@ -0,0 +1,673 @@
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
*
|
||||
* 模块名称 : 定时器模块
|
||||
* 文件名称 : bsp_timer.c
|
||||
* 版 本 : V1.3
|
||||
* 说 明 : 配置systick定时器作为系统滴答定时器。缺省定时周期为1ms。
|
||||
*
|
||||
* 实现了多个软件定时器供主程序使用(精度1ms), 可以通过修改 TMR_COUNT 增减定时器个数
|
||||
* 实现了ms级别延迟函数(精度1ms) 和us级延迟函数
|
||||
* 实现了系统运行时间函数(1ms单位)
|
||||
*
|
||||
* 修改记录 :
|
||||
* 版本号 日期 作者 说明
|
||||
* V1.0 2013-02-01 armfly 正式发布
|
||||
* V1.1 2013-06-21 armfly 增加us级延迟函数 bsp_DelayUS
|
||||
* V1.2 2014-09-07 armfly 增加TIM4 硬件定时中断,实现us级别定时.20us - 16秒
|
||||
* V1.3 2015-04-06 armfly 增加 bsp_CheckRunTime(int32_t _LastTime) 用来计算时间差值
|
||||
* V1.4 2015-05-22 armfly 完善 bsp_InitHardTimer() ,增加条件编译选择TIM2-5
|
||||
*
|
||||
* Copyright (C), 2015-2016, 安富莱电子 www.armfly.com
|
||||
*
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#include "bsp.h"
|
||||
|
||||
/*
|
||||
定义用于硬件定时器的TIM, 可以使 TIM2 - TIM5
|
||||
TIM3 和TIM4 是16位
|
||||
TIM2 和TIM5 是16位 (103是16位, 407是32位)
|
||||
*/
|
||||
#define USE_TIM2
|
||||
// #define USE_TIM3
|
||||
// #define USE_TIM4
|
||||
// #define USE_TIM5
|
||||
|
||||
#ifdef USE_TIM2
|
||||
#define TIM_HARD TIM2
|
||||
#define TIM_HARD_IRQn TIM2_IRQn
|
||||
#define TIM_HARD_RCC RCC_APB1Periph_TIM2
|
||||
#endif
|
||||
|
||||
#ifdef USE_TIM3
|
||||
#define TIM_HARD TIM3
|
||||
#define TIM_HARD_IRQn TIM3_IRQn
|
||||
#define TIM_HARD_RCC RCC_APB1Periph_TIM3
|
||||
#endif
|
||||
|
||||
#ifdef USE_TIM4
|
||||
#define TIM_HARD TIM4
|
||||
#define TIM_HARD_IRQn TIM4_IRQn
|
||||
#define TIM_HARD_RCC RCC_APB1Periph_TIM4
|
||||
#endif
|
||||
|
||||
#ifdef USE_TIM5
|
||||
#define TIM_HARD TIM5
|
||||
#define TIM_HARD_IRQn TIM5_IRQn
|
||||
#define TIM_HARD_RCC RCC_APB1Periph_TIM5
|
||||
#endif
|
||||
|
||||
/* 这2个全局变量转用于 bsp_DelayMS() 函数 */
|
||||
static volatile uint32_t s_uiDelayCount = 0;
|
||||
static volatile uint8_t s_ucTimeOutFlag = 0;
|
||||
|
||||
/* 定于软件定时器结构体变量 */
|
||||
static SOFT_TMR s_tTmr[TMR_COUNT];
|
||||
|
||||
/*
|
||||
全局运行时间,单位1ms
|
||||
最长可以表示 24.85天,如果你的产品连续运行时间超过这个数,则必须考虑溢出问题
|
||||
*/
|
||||
__IO int32_t g_iRunTime = 0;
|
||||
uint16_t init_100ms;
|
||||
static void bsp_SoftTimerDec(SOFT_TMR *_tmr);
|
||||
|
||||
/* 保存 TIM定时中断到后执行的回调函数指针 */
|
||||
static void (*s_TIM_CallBack1)(void);
|
||||
static void (*s_TIM_CallBack2)(void);
|
||||
static void (*s_TIM_CallBack3)(void);
|
||||
static void (*s_TIM_CallBack4)(void);
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_InitTimer
|
||||
* 功能说明: 配置systick中断,并初始化软件定时器变量
|
||||
* 形 参: 无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void bsp_InitTimer(void)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
/* 清零所有的软件定时器 */
|
||||
for (i = 0; i < TMR_COUNT; i++)
|
||||
{
|
||||
s_tTmr[i].Count = 0;
|
||||
s_tTmr[i].PreLoad = 0;
|
||||
s_tTmr[i].Flag = 0;
|
||||
s_tTmr[i].Mode = TMR_ONCE_MODE; /* 缺省是1次性工作模式 */
|
||||
}
|
||||
|
||||
/*
|
||||
配置systic中断周期为1ms,并启动systick中断。
|
||||
|
||||
SystemCoreClock 是固件中定义的系统内核时钟,对于STM32F4XX,一般为 168MHz
|
||||
|
||||
SysTick_Config() 函数的形参表示内核时钟多少个周期后触发一次Systick定时中断.
|
||||
-- SystemCoreClock / 1000 表示定时频率为 1000Hz, 也就是定时周期为 1ms
|
||||
-- SystemCoreClock / 500 表示定时频率为 500Hz, 也就是定时周期为 2ms
|
||||
-- SystemCoreClock / 2000 表示定时频率为 2000Hz, 也就是定时周期为 500us
|
||||
|
||||
对于常规的应用,我们一般取定时周期1ms。对于低速CPU或者低功耗应用,可以设置定时周期为 10ms
|
||||
*/
|
||||
SysTick_Config(SystemCoreClock / 1000);
|
||||
|
||||
#if defined(USE_TIM2) || defined(USE_TIM3) || defined(USE_TIM4) || defined(USE_TIM5)
|
||||
bsp_InitHardTimer();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: SysTick_ISR
|
||||
* 功能说明: SysTick中断服务程序,每隔1ms进入1次
|
||||
* 形 参: 无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
extern void bsp_RunPer1ms(void);
|
||||
extern void bsp_RunPer10ms(void);
|
||||
void SysTick_ISR(void)
|
||||
{
|
||||
static uint8_t s_count = 0;
|
||||
uint8_t i;
|
||||
|
||||
/* 每隔1ms进来1次 (仅用于 bsp_DelayMS) */
|
||||
if (s_uiDelayCount > 0)
|
||||
{
|
||||
if (--s_uiDelayCount == 0)
|
||||
{
|
||||
s_ucTimeOutFlag = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* 每隔1ms,对软件定时器的计数器进行减一操作 */
|
||||
for (i = 0; i < TMR_COUNT; i++)
|
||||
{
|
||||
bsp_SoftTimerDec(&s_tTmr[i]);
|
||||
}
|
||||
|
||||
/* 全局运行时间每1ms增1 */
|
||||
g_iRunTime++;
|
||||
init_100ms++;
|
||||
if (init_100ms > 100) // 100m's
|
||||
{
|
||||
init_100ms = 0;
|
||||
Flag_100ms = 1;
|
||||
}
|
||||
|
||||
if (g_iRunTime == 0x7FFFFFFF) /* 这个变量是 int32_t 类型,最大数为 0x7FFFFFFF */
|
||||
{
|
||||
g_iRunTime = 0;
|
||||
}
|
||||
|
||||
bsp_RunPer1ms(); /* 每隔1ms调用一次此函数,此函数在 bsp.c */
|
||||
|
||||
if (++s_count >= 10)
|
||||
{
|
||||
s_count = 0;
|
||||
|
||||
bsp_RunPer10ms(); /* 每隔10ms调用一次此函数,此函数在 bsp.c */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_SoftTimerDec
|
||||
* 功能说明: 每隔1ms对所有定时器变量减1。必须被SysTick_ISR周期性调用。
|
||||
* 形 参: _tmr : 定时器变量指针
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
static void bsp_SoftTimerDec(SOFT_TMR *_tmr)
|
||||
{
|
||||
if (_tmr->Count > 0)
|
||||
{
|
||||
/* 如果定时器变量减到1则设置定时器到达标志 */
|
||||
if (--_tmr->Count == 0)
|
||||
{
|
||||
_tmr->Flag = 1;
|
||||
|
||||
/* 如果是自动模式,则自动重装计数器 */
|
||||
if (_tmr->Mode == TMR_AUTO_MODE)
|
||||
{
|
||||
_tmr->Count = _tmr->PreLoad;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_DelayMS
|
||||
* 功能说明: ms级延迟,延迟精度为正负1ms
|
||||
* 形 参: n : 延迟长度,单位1 ms。 n 应大于2
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void bsp_DelayMS(uint32_t n)
|
||||
{
|
||||
if (n == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (n == 1)
|
||||
{
|
||||
n = 2;
|
||||
}
|
||||
|
||||
DISABLE_INT(); /* 关中断 */
|
||||
|
||||
s_uiDelayCount = n;
|
||||
s_ucTimeOutFlag = 0;
|
||||
|
||||
ENABLE_INT(); /* 开中断 */
|
||||
|
||||
while (1)
|
||||
{
|
||||
bsp_Idle(); /* CPU空闲执行的操作, 见 bsp.c 和 bsp.h 文件 */
|
||||
|
||||
/*
|
||||
等待延迟时间到
|
||||
注意:编译器认为 s_ucTimeOutFlag = 0,所以可能优化错误,因此 s_ucTimeOutFlag 变量必须申明为 volatile
|
||||
*/
|
||||
if (s_ucTimeOutFlag == 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_DelayUS
|
||||
* 功能说明: us级延迟。 必须在systick定时器启动后才能调用此函数。
|
||||
* 形 参: n : 延迟长度,单位1 us
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void bsp_DelayUS(uint32_t n)
|
||||
{
|
||||
uint32_t ticks;
|
||||
uint32_t told;
|
||||
uint32_t tnow;
|
||||
uint32_t tcnt = 0;
|
||||
uint32_t reload;
|
||||
|
||||
reload = SysTick->LOAD;
|
||||
ticks = n * (SystemCoreClock / 1000000); /* 需要的节拍数 */
|
||||
|
||||
tcnt = 0;
|
||||
told = SysTick->VAL; /* 刚进入时的计数器值 */
|
||||
|
||||
while (1)
|
||||
{
|
||||
tnow = SysTick->VAL;
|
||||
if (tnow != told)
|
||||
{
|
||||
/* SYSTICK是一个递减的计数器 */
|
||||
if (tnow < told)
|
||||
{
|
||||
tcnt += told - tnow;
|
||||
}
|
||||
/* 重新装载递减 */
|
||||
else
|
||||
{
|
||||
tcnt += reload - tnow + told;
|
||||
}
|
||||
told = tnow;
|
||||
|
||||
/* 时间超过/等于要延迟的时间,则退出 */
|
||||
if (tcnt >= ticks)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_StartTimer
|
||||
* 功能说明: 启动一个定时器,并设置定时周期。
|
||||
* 形 参: _id : 定时器ID,值域【0,TMR_COUNT-1】。用户必须自行维护定时器ID,以避免定时器ID冲突。
|
||||
* _period : 定时周期,单位1ms
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void bsp_StartTimer(uint8_t _id, uint32_t _period)
|
||||
{
|
||||
if (_id >= TMR_COUNT)
|
||||
{
|
||||
/* 打印出错的源代码文件名、函数名称 */
|
||||
BSP_Printf("Error: file %s, function %s()\r\n", __FILE__, __FUNCTION__);
|
||||
while (1)
|
||||
; /* 参数异常,死机等待看门狗复位 */
|
||||
}
|
||||
|
||||
DISABLE_INT(); /* 关中断 */
|
||||
|
||||
s_tTmr[_id].Count = _period; /* 实时计数器初值 */
|
||||
s_tTmr[_id].PreLoad = _period; /* 计数器自动重装值,仅自动模式起作用 */
|
||||
s_tTmr[_id].Flag = 0; /* 定时时间到标志 */
|
||||
s_tTmr[_id].Mode = TMR_ONCE_MODE; /* 1次性工作模式 */
|
||||
|
||||
ENABLE_INT(); /* 开中断 */
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_StartAutoTimer
|
||||
* 功能说明: 启动一个自动定时器,并设置定时周期。
|
||||
* 形 参: _id : 定时器ID,值域【0,TMR_COUNT-1】。用户必须自行维护定时器ID,以避免定时器ID冲突。
|
||||
* _period : 定时周期,单位10ms
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void bsp_StartAutoTimer(uint8_t _id, uint32_t _period)
|
||||
{
|
||||
if (_id >= TMR_COUNT)
|
||||
{
|
||||
/* 打印出错的源代码文件名、函数名称 */
|
||||
BSP_Printf("Error: file %s, function %s()\r\n", __FILE__, __FUNCTION__);
|
||||
while (1)
|
||||
; /* 参数异常,死机等待看门狗复位 */
|
||||
}
|
||||
|
||||
DISABLE_INT(); /* 关中断 */
|
||||
|
||||
s_tTmr[_id].Count = _period; /* 实时计数器初值 */
|
||||
s_tTmr[_id].PreLoad = _period; /* 计数器自动重装值,仅自动模式起作用 */
|
||||
s_tTmr[_id].Flag = 0; /* 定时时间到标志 */
|
||||
s_tTmr[_id].Mode = TMR_AUTO_MODE; /* 自动工作模式 */
|
||||
|
||||
ENABLE_INT(); /* 开中断 */
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_StopTimer
|
||||
* 功能说明: 停止一个定时器
|
||||
* 形 参: _id : 定时器ID,值域【0,TMR_COUNT-1】。用户必须自行维护定时器ID,以避免定时器ID冲突。
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void bsp_StopTimer(uint8_t _id)
|
||||
{
|
||||
if (_id >= TMR_COUNT)
|
||||
{
|
||||
/* 打印出错的源代码文件名、函数名称 */
|
||||
BSP_Printf("Error: file %s, function %s()\r\n", __FILE__, __FUNCTION__);
|
||||
while (1)
|
||||
; /* 参数异常,死机等待看门狗复位 */
|
||||
}
|
||||
|
||||
DISABLE_INT(); /* 关中断 */
|
||||
|
||||
s_tTmr[_id].Count = 0; /* 实时计数器初值 */
|
||||
s_tTmr[_id].Flag = 0; /* 定时时间到标志 */
|
||||
s_tTmr[_id].Mode = TMR_ONCE_MODE; /* 自动工作模式 */
|
||||
|
||||
ENABLE_INT(); /* 开中断 */
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_CheckTimer
|
||||
* 功能说明: 检测定时器是否超时
|
||||
* 形 参: _id : 定时器ID,值域【0,TMR_COUNT-1】。用户必须自行维护定时器ID,以避免定时器ID冲突。
|
||||
* _period : 定时周期,单位1ms
|
||||
* 返 回 值: 返回 0 表示定时未到, 1表示定时到
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
uint8_t bsp_CheckTimer(uint8_t _id)
|
||||
{
|
||||
if (_id >= TMR_COUNT)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s_tTmr[_id].Flag == 1)
|
||||
{
|
||||
s_tTmr[_id].Flag = 0;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_GetRunTime
|
||||
* 功能说明: 获取CPU运行时间,单位1ms。最长可以表示 24.85天,如果你的产品连续运行时间超过这个数,则必须考虑溢出问题
|
||||
* 形 参: 无
|
||||
* 返 回 值: CPU运行时间,单位1ms
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
int32_t bsp_GetRunTime(void)
|
||||
{
|
||||
int32_t runtime;
|
||||
|
||||
DISABLE_INT(); /* 关中断 */
|
||||
|
||||
runtime = g_iRunTime; /* 这个变量在Systick中断中被改写,因此需要关中断进行保护 */
|
||||
|
||||
ENABLE_INT(); /* 开中断 */
|
||||
|
||||
return runtime;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_CheckRunTime
|
||||
* 功能说明: 计算当前运行时间和给定时刻之间的差值。处理了计数器循环。
|
||||
* 形 参: _LastTime 上个时刻
|
||||
* 返 回 值: 当前时间和过去时间的差值,单位1ms
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
int32_t bsp_CheckRunTime(int32_t _LastTime)
|
||||
{
|
||||
int32_t now_time;
|
||||
int32_t time_diff;
|
||||
|
||||
DISABLE_INT(); /* 关中断 */
|
||||
|
||||
now_time = g_iRunTime; /* 这个变量在Systick中断中被改写,因此需要关中断进行保护 */
|
||||
|
||||
ENABLE_INT(); /* 开中断 */
|
||||
|
||||
if (now_time >= _LastTime)
|
||||
{
|
||||
time_diff = now_time - _LastTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
time_diff = 0x7FFFFFFF - _LastTime + now_time;
|
||||
}
|
||||
|
||||
return time_diff;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: SysTick_Handler
|
||||
* 功能说明: 系统嘀嗒定时器中断服务程序。启动文件中引用了该函数。
|
||||
* 形 参: 无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void SysTick_Handler(void)
|
||||
{
|
||||
SysTick_ISR();
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_InitHardTimer
|
||||
* 功能说明: 配置 TIMx,用于us级别硬件定时。TIMx将自由运行,永不停止.
|
||||
* TIMx可以用TIM2 - TIM5 之间的TIM, 这些TIM有4个通道, 挂在 APB1 上,输入时钟=SystemCoreClock / 2
|
||||
* 形 参: 无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
#if defined(USE_TIM2) || defined(USE_TIM3) || defined(USE_TIM4) || defined(USE_TIM5)
|
||||
void bsp_InitHardTimer(void)
|
||||
{
|
||||
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
|
||||
uint32_t usPeriod;
|
||||
uint16_t usPrescaler;
|
||||
uint32_t uiTIMxCLK;
|
||||
|
||||
/* 使能TIM时钟 */
|
||||
RCC_APB1PeriphClockCmd(TIM_HARD_RCC, ENABLE);
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
system_stm32f4xx.c 文件中 void SetSysClock(void) 函数对时钟的配置如下:
|
||||
|
||||
HCLK = SYSCLK / 1 (AHB1Periph)
|
||||
PCLK2 = HCLK / 2 (APB2Periph)
|
||||
PCLK1 = HCLK / 4 (APB1Periph)
|
||||
|
||||
因为APB1 prescaler != 1, 所以 APB1上的TIMxCLK = PCLK1 x 2 = SystemCoreClock / 2;
|
||||
因为APB2 prescaler != 1, 所以 APB2上的TIMxCLK = PCLK2 x 2 = SystemCoreClock;
|
||||
|
||||
APB1 定时器有 TIM2, TIM3 ,TIM4, TIM5, TIM6, TIM7, TIM12, TIM13,TIM14
|
||||
APB2 定时器有 TIM1, TIM8 ,TIM9, TIM10, TIM11
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
uiTIMxCLK = SystemCoreClock / 2;
|
||||
|
||||
usPrescaler = uiTIMxCLK / 1000000; /* 分频到周期 1us */
|
||||
|
||||
#if defined(USE_TIM2) || defined(USE_TIM5)
|
||||
// usPeriod = 0xFFFFFFFF; /* 407支持32位定时器 */
|
||||
usPeriod = 0xFFFF; /* 103支持16位 */
|
||||
#else
|
||||
usPeriod = 0xFFFF;
|
||||
#endif
|
||||
/* Time base configuration */
|
||||
TIM_TimeBaseStructure.TIM_Period = usPeriod;
|
||||
TIM_TimeBaseStructure.TIM_Prescaler = usPrescaler;
|
||||
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
|
||||
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
|
||||
|
||||
TIM_TimeBaseInit(TIM_HARD, &TIM_TimeBaseStructure);
|
||||
|
||||
// TIM_ARRPreloadConfig(TIMx, ENABLE);
|
||||
|
||||
/* TIMx enable counter */
|
||||
TIM_Cmd(TIM_HARD, ENABLE);
|
||||
|
||||
/* 配置TIM定时中断 (Update) */
|
||||
{
|
||||
NVIC_InitTypeDef NVIC_InitStructure; /* 中断结构体在 misc.h 中定义 */
|
||||
|
||||
NVIC_InitStructure.NVIC_IRQChannel = TIM_HARD_IRQn;
|
||||
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 4; /* 比串口优先级低 */
|
||||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_Init(&NVIC_InitStructure);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: bsp_StartHardTimer
|
||||
* 功能说明: 使用TIM2-5做单次定时器使用, 定时时间到后执行回调函数。可以同时启动4个定时器,互不干扰。
|
||||
* 定时精度正负10us (主要耗费在调用本函数的执行时间,函数内部进行了补偿减小误差)
|
||||
* TIM2和TIM5 是16位定时器。
|
||||
* TIM3和TIM4 是16位定时器。
|
||||
* 形 参: _CC : 捕获通道几,1,2,3, 4
|
||||
* _uiTimeOut : 超时时间, 单位 1us. 对于16位定时器,最大 65.5ms; 对于32位定时器,最大 4294秒
|
||||
* _pCallBack : 定时时间到后,被执行的函数
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void bsp_StartHardTimer(uint8_t _CC, uint32_t _uiTimeOut, void *_pCallBack)
|
||||
{
|
||||
uint32_t cnt_now;
|
||||
uint32_t cnt_tar;
|
||||
|
||||
/*
|
||||
执行下面这个语句,时长 = 18us (通过逻辑分析仪测量IO翻转)
|
||||
bsp_StartTimer2(3, 500, (void *)test1);
|
||||
*/
|
||||
if (_uiTimeOut < 5)
|
||||
{
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
_uiTimeOut -= 5;
|
||||
}
|
||||
|
||||
cnt_now = TIM_GetCounter(TIM_HARD); /* 读取当前的计数器值 */
|
||||
cnt_tar = cnt_now + _uiTimeOut; /* 计算捕获的计数器值 */
|
||||
if (_CC == 1)
|
||||
{
|
||||
s_TIM_CallBack1 = (void (*)(void))_pCallBack;
|
||||
|
||||
TIM_SetCompare1(TIM_HARD, cnt_tar); /* 设置捕获比较计数器CC1 */
|
||||
TIM_ClearITPendingBit(TIM_HARD, TIM_IT_CC1);
|
||||
TIM_ITConfig(TIM_HARD, TIM_IT_CC1, ENABLE); /* 使能CC1中断 */
|
||||
}
|
||||
else if (_CC == 2)
|
||||
{
|
||||
s_TIM_CallBack2 = (void (*)(void))_pCallBack;
|
||||
|
||||
TIM_SetCompare2(TIM_HARD, cnt_tar); /* 设置捕获比较计数器CC2 */
|
||||
TIM_ClearITPendingBit(TIM_HARD, TIM_IT_CC2);
|
||||
TIM_ITConfig(TIM_HARD, TIM_IT_CC2, ENABLE); /* 使能CC2中断 */
|
||||
}
|
||||
else if (_CC == 3)
|
||||
{
|
||||
s_TIM_CallBack3 = (void (*)(void))_pCallBack;
|
||||
|
||||
TIM_SetCompare3(TIM_HARD, cnt_tar); /* 设置捕获比较计数器CC3 */
|
||||
TIM_ClearITPendingBit(TIM_HARD, TIM_IT_CC3);
|
||||
TIM_ITConfig(TIM_HARD, TIM_IT_CC3, ENABLE); /* 使能CC3中断 */
|
||||
}
|
||||
else if (_CC == 4)
|
||||
{
|
||||
s_TIM_CallBack4 = (void (*)(void))_pCallBack;
|
||||
|
||||
TIM_SetCompare4(TIM_HARD, cnt_tar); /* 设置捕获比较计数器CC4 */
|
||||
TIM_ClearITPendingBit(TIM_HARD, TIM_IT_CC4);
|
||||
TIM_ITConfig(TIM_HARD, TIM_IT_CC4, ENABLE); /* 使能CC4中断 */
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: TIMx_IRQHandler
|
||||
* 功能说明: TIM 中断服务程序
|
||||
* 形 参:无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#ifdef USE_TIM2
|
||||
void TIM2_IRQHandler(void)
|
||||
#endif
|
||||
|
||||
#ifdef USE_TIM3
|
||||
void TIM3_IRQHandler(void)
|
||||
#endif
|
||||
|
||||
#ifdef USE_TIM4
|
||||
void TIM4_IRQHandler(void)
|
||||
#endif
|
||||
|
||||
#ifdef USE_TIM5
|
||||
void TIM5_IRQHandler(void)
|
||||
#endif
|
||||
{
|
||||
if (TIM_GetITStatus(TIM_HARD, TIM_IT_CC1))
|
||||
{
|
||||
TIM_ClearITPendingBit(TIM_HARD, TIM_IT_CC1);
|
||||
TIM_ITConfig(TIM_HARD, TIM_IT_CC1, DISABLE); /* 禁能CC1中断 */
|
||||
|
||||
/* 先关闭中断,再执行回调函数。因为回调函数可能需要重启定时器 */
|
||||
s_TIM_CallBack1();
|
||||
}
|
||||
|
||||
if (TIM_GetITStatus(TIM_HARD, TIM_IT_CC2))
|
||||
{
|
||||
TIM_ClearITPendingBit(TIM_HARD, TIM_IT_CC2);
|
||||
TIM_ITConfig(TIM_HARD, TIM_IT_CC2, DISABLE); /* 禁能CC2中断 */
|
||||
|
||||
/* 先关闭中断,再执行回调函数。因为回调函数可能需要重启定时器 */
|
||||
s_TIM_CallBack2();
|
||||
}
|
||||
|
||||
if (TIM_GetITStatus(TIM_HARD, TIM_IT_CC3))
|
||||
{
|
||||
TIM_ClearITPendingBit(TIM_HARD, TIM_IT_CC3);
|
||||
TIM_ITConfig(TIM_HARD, TIM_IT_CC3, DISABLE); /* 禁能CC3中断 */
|
||||
|
||||
/* 先关闭中断,再执行回调函数。因为回调函数可能需要重启定时器 */
|
||||
s_TIM_CallBack3();
|
||||
}
|
||||
|
||||
if (TIM_GetITStatus(TIM_HARD, TIM_IT_CC4))
|
||||
{
|
||||
TIM_ClearITPendingBit(TIM_HARD, TIM_IT_CC4);
|
||||
TIM_ITConfig(TIM_HARD, TIM_IT_CC4, DISABLE); /* 禁能CC4中断 */
|
||||
|
||||
/* 先关闭中断,再执行回调函数。因为回调函数可能需要重启定时器 */
|
||||
s_TIM_CallBack4();
|
||||
}
|
||||
}
|
||||
|
||||
/***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
|
||||
214
User/bsp/src/bsp_usart_dma.c
Normal file
214
User/bsp/src/bsp_usart_dma.c
Normal file
@@ -0,0 +1,214 @@
|
||||
|
||||
#include "bsp_usart_dma.h"
|
||||
#include "string.h"
|
||||
|
||||
uint8_t ReceiveBuff[RECEIVEBUFF_SIZE];
|
||||
uint8_t g_ucRxRcvNewFlag;
|
||||
uint8_t g_RxBuf[64];
|
||||
|
||||
/**
|
||||
* @brief USART GPIO 配置,工作参数配置
|
||||
* @param 无
|
||||
* @retval 无
|
||||
*/
|
||||
void USART_Config(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
USART_InitTypeDef USART_InitStructure;
|
||||
NVIC_InitTypeDef NVIC_InitStruct;
|
||||
// 打开串口GPIO的时钟
|
||||
DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);
|
||||
|
||||
// 打开串口外设的时钟
|
||||
DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);
|
||||
|
||||
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
|
||||
NVIC_InitStruct.NVIC_IRQChannel = DEBUG_USART_IRQ;
|
||||
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
|
||||
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 3;
|
||||
NVIC_Init(&NVIC_InitStruct);
|
||||
|
||||
// 将USART Tx的GPIO配置为推挽复用模式
|
||||
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||||
GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);
|
||||
|
||||
// 将USART Rx的GPIO配置为浮空输入模式
|
||||
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
|
||||
GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
|
||||
|
||||
// 配置串口的工作参数
|
||||
// 配置波特率
|
||||
USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
|
||||
// 配置 针数据字长
|
||||
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
|
||||
// 配置停止位
|
||||
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(DEBUG_USARTx, &USART_InitStructure);
|
||||
// 使能空闲中断
|
||||
USART_ITConfig(DEBUG_USARTx, USART_IT_IDLE, ENABLE);
|
||||
// 使能串口
|
||||
USART_Cmd(DEBUG_USARTx, ENABLE);
|
||||
}
|
||||
|
||||
/***************** 发送一个字节 **********************/
|
||||
void Usart_SendByte(USART_TypeDef *pUSARTx, uint8_t ch)
|
||||
{
|
||||
/* 发送一个字节数据到USART */
|
||||
USART_SendData(pUSARTx, ch);
|
||||
|
||||
/* 等待发送数据寄存器为空 */
|
||||
while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET)
|
||||
;
|
||||
}
|
||||
|
||||
/****************** 发送8位的数组 ************************/
|
||||
void Usart_SendArray(USART_TypeDef *pUSARTx, uint8_t *array, uint16_t num)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
/* 发送一个字节数据到USART */
|
||||
Usart_SendByte(pUSARTx, array[i]);
|
||||
}
|
||||
/* 等待发送完成 */
|
||||
while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TC) == RESET)
|
||||
;
|
||||
}
|
||||
|
||||
/***************** 发送字符串 **********************/
|
||||
void Usart_SendString(USART_TypeDef *pUSARTx, char *str)
|
||||
{
|
||||
unsigned int k = 0;
|
||||
do
|
||||
{
|
||||
Usart_SendByte(pUSARTx, *(str + k));
|
||||
k++;
|
||||
} while (*(str + k) != '\0');
|
||||
|
||||
/* 等待发送完成 */
|
||||
while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TC) == RESET)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/***************** 发送一个16位数 **********************/
|
||||
void Usart_SendHalfWord(USART_TypeDef *pUSARTx, uint16_t ch)
|
||||
{
|
||||
uint8_t temp_h, temp_l;
|
||||
|
||||
/* 取出高八位 */
|
||||
temp_h = (ch & 0XFF00) >> 8;
|
||||
/* 取出低八位 */
|
||||
temp_l = ch & 0XFF;
|
||||
|
||||
/* 发送高八位 */
|
||||
USART_SendData(pUSARTx, temp_h);
|
||||
while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET)
|
||||
;
|
||||
|
||||
/* 发送低八位 */
|
||||
USART_SendData(pUSARTx, temp_l);
|
||||
while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET)
|
||||
;
|
||||
}
|
||||
|
||||
/// 重定向c库函数printf到串口,重定向后可使用printf函数
|
||||
int fputc(int ch, FILE *f)
|
||||
{
|
||||
/* 发送一个字节数据到串口 */
|
||||
USART_SendData(DEBUG_USARTx, (uint8_t)ch);
|
||||
|
||||
/* 等待发送完毕 */
|
||||
while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET)
|
||||
;
|
||||
|
||||
return (ch);
|
||||
}
|
||||
|
||||
/// 重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数
|
||||
int fgetc(FILE *f)
|
||||
{
|
||||
/* 等待串口输入数据 */
|
||||
while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) == RESET)
|
||||
;
|
||||
|
||||
return (int)USART_ReceiveData(DEBUG_USARTx);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USARTx TX DMA 配置,内存到外设(USART1->DR)
|
||||
* @param 无
|
||||
* @retval 无
|
||||
*/
|
||||
void USARTx_DMA_Config(void)
|
||||
{
|
||||
DMA_InitTypeDef DMA_InitStructure;
|
||||
// 开启DMA时钟
|
||||
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
|
||||
|
||||
// 设置DMA源地址:串口数据寄存器地址*/
|
||||
DMA_InitStructure.DMA_PeripheralBaseAddr = USART_DR_ADDRESS;
|
||||
// 内存地址(要传输的变量的指针)
|
||||
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ReceiveBuff;
|
||||
// 方向:从外设到内存
|
||||
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
|
||||
// 传输大小
|
||||
DMA_InitStructure.DMA_BufferSize = RECEIVEBUFF_SIZE;
|
||||
// 外设地址不增
|
||||
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
||||
// 内存地址自增
|
||||
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
||||
// 外设数据单位
|
||||
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
||||
// 内存数据单位
|
||||
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
||||
// DMA模式,一次或者循环模式
|
||||
// DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;
|
||||
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
|
||||
// 优先级:中
|
||||
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
|
||||
// 禁止内存到内存的传输
|
||||
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
|
||||
// 配置DMA通道
|
||||
DMA_Init(USART_RX_DMA_CHANNEL, &DMA_InitStructure);
|
||||
// 使能DMA
|
||||
DMA_Cmd(USART_RX_DMA_CHANNEL, ENABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 串口空闲中断.
|
||||
* @param 无
|
||||
* @retval 无
|
||||
*/
|
||||
void DEBUG_USART_IRQHandler(void)
|
||||
{
|
||||
uint16_t t;
|
||||
if (USART_GetITStatus(DEBUG_USARTx, USART_IT_IDLE) == SET) // 检查中断是否发生
|
||||
{
|
||||
DMA_Cmd(USART_RX_DMA_CHANNEL, DISABLE); // 关闭DMA传输
|
||||
|
||||
t = DMA_GetCurrDataCounter(USART_RX_DMA_CHANNEL); // 获取剩余的数据数量
|
||||
memset(g_RxBuf, 0, sizeof g_RxBuf);
|
||||
memcpy(g_RxBuf, ReceiveBuff, RECEIVEBUFF_SIZE - t);
|
||||
memset(ReceiveBuff, 0, sizeof ReceiveBuff);
|
||||
g_ucRxRcvNewFlag = 1;
|
||||
|
||||
DMA_SetCurrDataCounter(USART_RX_DMA_CHANNEL, RECEIVEBUFF_SIZE); // 重新设置传输的数据数量
|
||||
DMA_Cmd(USART_RX_DMA_CHANNEL, ENABLE); // 开启DMA传输
|
||||
|
||||
USART_ReceiveData(DEBUG_USARTx); // 读取一次数据,不然会一直进中断
|
||||
USART_ClearFlag(DEBUG_USARTx, USART_FLAG_IDLE); // 清除串口空闲中断标志位
|
||||
}
|
||||
}
|
||||
58
User/bsp/stm32f10x_assert.c
Normal file
58
User/bsp/stm32f10x_assert.c
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
*
|
||||
* 模块名称 : 断言模块。
|
||||
* 文件名称 : stm32f10x_assert.c
|
||||
* 版 本 : V1.0
|
||||
* 说 明 : 提供断言函数,主要用于程序调试。ST固件库中的函数均可以对输入参数进行检查,提高程序的健壮性。
|
||||
* 这个文件是安富莱电子创建的文件,不属于标准库的文件,ST固件库的范例将这些函数放在main.c文件。
|
||||
* 我们认为这个和用户的具体应用无关,因此将其独立出来,使main.c文件看起来更加简洁一些。
|
||||
* 修改记录 :
|
||||
* 版本号 日期 作者 说明
|
||||
* v1.0 2011-08-27 armfly ST固件库V3.4.0版本。
|
||||
* v2.0 2011-10-16 armfly ST固件库V3.5.0版本。
|
||||
*
|
||||
* Copyright (C), 2010-2011, 安富莱电子 www.armfly.com
|
||||
*
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#include "stm32f10x.h" /* 这个文件包含了stm32f10x_conf.h, stm32f10x_conf.h文件定义了USE_FULL_ASSERT */
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
ST库函数使用了C编译器的断言功能,如果定义了USE_FULL_ASSERT,那么所有的ST库函数将检查函数形参
|
||||
是否正确。如果不正确将调用 assert_failed() 函数,这个函数是一个死循环,便于用户检查代码。
|
||||
|
||||
关键字 __LINE__ 表示源代码行号。
|
||||
关键字__FILE__表示源代码文件名。
|
||||
|
||||
断言功能使能后将增大代码大小,推荐用户仅在调试时使能,在正式发布软件是禁止。
|
||||
|
||||
用户可以选择是否使能ST固件库的断言供能。使能断言的方法有两种:
|
||||
(1) 在C编译器的预定义宏选项中定义USE_FULL_ASSERT。
|
||||
(2) 在本文件取消"#define USE_FULL_ASSERT 1"行的注释。
|
||||
*/
|
||||
#ifdef USE_FULL_ASSERT
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: assert_failed
|
||||
* 形 参:file : 源代码文件名称。关键字__FILE__表示源代码文件名。
|
||||
* line :代码行号。关键字 __LINE__ 表示源代码行号
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void assert_failed(uint8_t *file, uint32_t line)
|
||||
{
|
||||
/*
|
||||
用户可以添加自己的代码报告源代码文件名和代码行号,比如将错误文件和行号打印到串口
|
||||
printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
|
||||
*/
|
||||
|
||||
/* 这是一个死循环,断言失败时程序会在此处死机,以便于用户查错 */
|
||||
while (1)
|
||||
{
|
||||
}
|
||||
}
|
||||
#endif
|
||||
72
User/bsp/stm32f10x_conf.h
Normal file
72
User/bsp/stm32f10x_conf.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
*
|
||||
* 模块名称 : STM32固件库配置文件。
|
||||
* 文件名称 : stm32f10x_conf.h
|
||||
* 版 本 : V3.5.0
|
||||
* 说 明 : 这是ST固件库提供的文件。用户可以根据需要包含ST固件库的外设模块。为了方便我们包含了所有固件
|
||||
* 库模块。
|
||||
*
|
||||
* 这个文件被 Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h 包含,因此
|
||||
* 我们在.c文件中只需要 include "stm32f10x.h"即可,不必单独再include stm32f10x_conf.h文件
|
||||
* 修改记录 :
|
||||
* 版本号 日期 作者 说明
|
||||
* v1.0 2011-09-20 armfly ST固件库升级到V3.4.0版本。
|
||||
* v2.0 2011-11-16 armfly ST固件库升级到V3.5.0版本。
|
||||
*
|
||||
* Copyright (C), 2010-2011, 安富莱电子 www.armfly.com
|
||||
*
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __STM32F10x_CONF_H
|
||||
#define __STM32F10x_CONF_H
|
||||
|
||||
/* 未注释的行表示包含对应的外设头文件 */
|
||||
#include "stm32f10x_adc.h"
|
||||
#include "stm32f10x_bkp.h"
|
||||
#include "stm32f10x_can.h"
|
||||
#include "stm32f10x_cec.h"
|
||||
#include "stm32f10x_crc.h"
|
||||
#include "stm32f10x_dac.h"
|
||||
#include "stm32f10x_dbgmcu.h"
|
||||
#include "stm32f10x_dma.h"
|
||||
#include "stm32f10x_exti.h"
|
||||
#include "stm32f10x_flash.h"
|
||||
#include "stm32f10x_fsmc.h"
|
||||
#include "stm32f10x_gpio.h"
|
||||
#include "stm32f10x_i2c.h"
|
||||
#include "stm32f10x_iwdg.h"
|
||||
#include "stm32f10x_pwr.h"
|
||||
#include "stm32f10x_rcc.h"
|
||||
#include "stm32f10x_rtc.h"
|
||||
#include "stm32f10x_sdio.h"
|
||||
#include "stm32f10x_spi.h"
|
||||
#include "stm32f10x_tim.h"
|
||||
#include "stm32f10x_usart.h"
|
||||
#include "stm32f10x_wwdg.h"
|
||||
#include "misc.h" /* 用于NVIC和SysTick的高级函数(与CMSIS相关) */
|
||||
|
||||
/*
|
||||
用户可以选择是否使能ST固件库的断言供能。使能断言的方法有两种:
|
||||
(1) 在C编译器的预定义宏选项中定义USE_FULL_ASSERT。
|
||||
(2) 在本文件取消"#define USE_FULL_ASSERT 1"行的注释。
|
||||
*/
|
||||
/* 取消下面代码行的注释则固件库代码会展开assert_param宏进行断言 */
|
||||
/* #define USE_FULL_ASSERT 1 */
|
||||
|
||||
#ifdef USE_FULL_ASSERT
|
||||
/*
|
||||
assert_param宏用于函数形参检查。如果expr是false,它将调用assert_failed()函数报告发生错误的源文件
|
||||
和行号。如果expr是true,将不执行任何操作。
|
||||
|
||||
assert_failed() 函数在stm32f10x_assert.c文件(这是安富莱建立的文件)
|
||||
*/
|
||||
#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
|
||||
|
||||
void assert_failed(uint8_t* file, uint32_t line);
|
||||
#else
|
||||
#define assert_param(expr) ((void)0)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
217
User/bsp/stm32f10x_it.c
Normal file
217
User/bsp/stm32f10x_it.c
Normal file
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
*
|
||||
* 模块名称 : 中断模块
|
||||
* 文件名称 : stm32f10x_it.c
|
||||
* 版 本 : V2.0
|
||||
* 说 明 : 本文件存放所有的中断服务函数。为了便于他人了解程序用到的中断,我们不建议将中断函数移到其他
|
||||
* 的文件。
|
||||
*
|
||||
* 我们只需要添加需要的中断函数即可。一般中断函数名是固定的,除非您修改了启动文件:
|
||||
* Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm\startup_stm32f10x_hd.s
|
||||
*
|
||||
* 启动文件是汇编语言文件,定了每个中断的服务函数,这些函数使用了WEAK 关键字,表示弱定义,因此如
|
||||
* 果我们在c文件中重定义了该服务函数(必须和它同名),那么启动文件的中断函数将自动无效。这也就
|
||||
* 函数重定义的概念,这和C++中的函数重载的意义类似。
|
||||
*
|
||||
* 修改记录 :
|
||||
* 版本号 日期 作者 说明
|
||||
* v0.1 2009-12-27 armfly 创建该文件,ST固件库版本为V3.1.2
|
||||
* v1.0 2011-01-11 armfly ST固件库升级到V3.4.0版本。
|
||||
* v2.0 2011-10-16 armfly ST固件库升级到V3.5.0版本。
|
||||
* V2.1 2015-08-07 armfly 在异常中断那服务器程序中驱动蜂鸣器发声,提示有问题了
|
||||
*
|
||||
* Copyright (C), 2010-2011, 安富莱电子 www.armfly.com
|
||||
*
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#include "stm32f10x_it.h"
|
||||
|
||||
#define ERR_INFO "\r\nEnter HardFault_Handler, System Halt.\r\n"
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* Cortex-M3 内核异常中断服务程序
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: NMI_Handler
|
||||
* 功能说明: 不可屏蔽中断服务程序。
|
||||
* 形 参:无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void NMI_Handler(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: HardFault_Handler
|
||||
* 功能说明: 硬件失效中断服务程序。
|
||||
* 形 参:无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void HardFault_Handler(void)
|
||||
{
|
||||
#if 0
|
||||
const char *pError = ERR_INFO;
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < sizeof(ERR_INFO); i++)
|
||||
{
|
||||
USART1->DR = pError[i];
|
||||
/* 等待发送结束 */
|
||||
while ((USART1->SR & USART_FLAG_TC) == (uint16_t)RESET);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0 /* 出现异常时,驱动蜂鸣器发声 */
|
||||
while(1)
|
||||
{
|
||||
uint16_t m;
|
||||
|
||||
GPIOA->ODR ^= GPIO_Pin_8;
|
||||
|
||||
for (m = 0; m < 10000; m++);
|
||||
}
|
||||
#else
|
||||
|
||||
/* 当硬件失效异常发生时进入死循环 */
|
||||
while (1)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: MemManage_Handler
|
||||
* 功能说明: 内存管理异常中断服务程序。
|
||||
* 形 参:无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void MemManage_Handler(void)
|
||||
{
|
||||
/* 当内存管理异常发生时进入死循环 */
|
||||
while (1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: BusFault_Handler
|
||||
* 功能说明: 总线访问异常中断服务程序。
|
||||
* 形 参:无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void BusFault_Handler(void)
|
||||
{
|
||||
/* 当总线异常时进入死循环 */
|
||||
while (1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: UsageFault_Handler
|
||||
* 功能说明: 未定义的指令或非法状态中断服务程序。
|
||||
* 形 参:无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void UsageFault_Handler(void)
|
||||
{
|
||||
/* 当用法异常时进入死循环 */
|
||||
while (1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: SVC_Handler
|
||||
* 功能说明: 通过SWI指令的系统服务调用中断服务程序。
|
||||
* 形 参:无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void SVC_Handler(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: DebugMon_Handler
|
||||
* 功能说明: 调试监视器中断服务程序。
|
||||
* 形 参:无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void DebugMon_Handler(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: PendSV_Handler
|
||||
* 功能说明: 可挂起的系统服务调用中断服务程序。
|
||||
* 形 参:无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void PendSV_Handler(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* STM32F10x内部外设中断服务程序
|
||||
* 用户在此添加用到外设中断服务函数。有效的中断服务函数名请参考启动文件(startup_stm32f10x_xx.s)
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* 函 数 名: PPP_IRQHandler
|
||||
* 功能说明: 外设中断服务程序。
|
||||
* 形 参:无
|
||||
* 返 回 值: 无
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
/*
|
||||
因为中断服务程序往往和具体的应用有关,会用到用户功能模块的变量、函数。如果在本文件展开,会增加大量的
|
||||
外部变量声明或者include语句。
|
||||
|
||||
因此,我们推荐这个地方只写一个调用语句,中断服务函数的本体放到对应的用户功能模块中。
|
||||
增加一层调用会降低代码的执行效率,不过我们宁愿损失这个效率,从而增强程序的模块化特性。
|
||||
|
||||
增加extern关键字,直接引用用到的外部函数,避免在文件头include其他模块的头文件
|
||||
extern void ppp_ISR(void);
|
||||
void PPP_IRQHandler(void)
|
||||
{
|
||||
ppp_ISR();
|
||||
}
|
||||
*/
|
||||
extern void can_ISR(void);
|
||||
extern void USB_Istr(void);
|
||||
void USB_LP_CAN1_RX0_IRQHandler(void)
|
||||
{
|
||||
/* 判断CAN1的时钟是否打开 */
|
||||
if (RCC->APB1ENR & RCC_APB1Periph_CAN1)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
|
||||
35
User/bsp/stm32f10x_it.h
Normal file
35
User/bsp/stm32f10x_it.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
*
|
||||
* 模块名称 : 中断模块
|
||||
* 文件名称 : stm32f10x_it.h
|
||||
* 版 本 : V2.0
|
||||
* 说 明 : 头文件
|
||||
* 修改记录 :
|
||||
* 版本号 日期 作者 说明
|
||||
* v1.0 2011-05-13 armfly ST固件库V3.4.0版本
|
||||
* v2.0 2011-10-16 armfly ST固件库V3.5.0版本
|
||||
*
|
||||
* Copyright (C), 2010-2011, 安富莱电子 www.armfly.com
|
||||
*
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __STM32F10x_IT_H
|
||||
#define __STM32F10x_IT_H
|
||||
|
||||
#include "stm32f10x.h"
|
||||
|
||||
void NMI_Handler(void);
|
||||
void HardFault_Handler(void);
|
||||
void MemManage_Handler(void);
|
||||
void BusFault_Handler(void);
|
||||
void UsageFault_Handler(void);
|
||||
void SVC_Handler(void);
|
||||
void DebugMon_Handler(void);
|
||||
void PendSV_Handler(void);
|
||||
void SysTick_Handler(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
1094
User/bsp/system_stm32f10x.c
Normal file
1094
User/bsp/system_stm32f10x.c
Normal file
File diff suppressed because it is too large
Load Diff
98
User/bsp/system_stm32f10x.h
Normal file
98
User/bsp/system_stm32f10x.h
Normal file
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file system_stm32f10x.h
|
||||
* @author MCD Application Team
|
||||
* @version V3.5.0
|
||||
* @date 11-March-2011
|
||||
* @brief CMSIS Cortex-M3 Device Peripheral Access Layer System Header File.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/** @addtogroup CMSIS
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup stm32f10x_system
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Define to prevent recursive inclusion
|
||||
*/
|
||||
#ifndef __SYSTEM_STM32F10X_H
|
||||
#define __SYSTEM_STM32F10X_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @addtogroup STM32F10x_System_Includes
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @addtogroup STM32F10x_System_Exported_types
|
||||
* @{
|
||||
*/
|
||||
|
||||
extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32F10x_System_Exported_Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32F10x_System_Exported_Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32F10x_System_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
extern void SystemInit(void);
|
||||
extern void SystemCoreClockUpdate(void);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*__SYSTEM_STM32F10X_H */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
|
||||
Reference in New Issue
Block a user