This commit is contained in:
刘正航
2026-04-16 16:55:01 +08:00
commit 609eb878d1
624 changed files with 214375 additions and 0 deletions

View 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
View 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) *********************************/

View 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) *********************************/

View 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.0usSCL低电平时间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
View 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.0usSCL低电平时间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/272MHz 系统 = 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 ---------------------------------