2016TI杯——寻迹小车

2016TI杯——寻迹小车首先,我选择的是B题————自动循迹小车,具体如下:B题:自动循迹小车1.任务设计制作一个自动循迹小车。小车采用一片TI公司LDC1314或LDC1000电感数字转换器作为循迹传感器,在规定的平面跑道自动按顺时针方向循迹前进。跑道的标识为一根直径0.6~0.9mm的细铁丝,按照图1的示意尺寸,用透明胶带将其贴在跑道上。图中所有圆弧的半径均为为20cm±2cm。图1跑道示意图

大家好,又见面了,我是你们的朋友全栈君。

首先,我选择的是B题————自动循迹小车,具体如下:

B题:自动循迹小车
1.任务
设计制作一个自动循迹小车。小车采用一片 TI公司LDC1314或LDC1000电感数字转换器作为循迹传感器,在规定的平面跑道自动按顺时针方向循迹前进。跑道的标识为一根直径0.6~0.9mm的细铁丝,按照图1的示意尺寸,用透明胶带将其贴在跑道上。图中所有圆弧的半径均为为20cm±2cm。
这里写图片描述
图1 跑道示意图
2.要求
(1)在图1小车所在的直线区任意指定一起点(终点),小车依据跑道上设置的铁丝标识,自动绕跑道跑完一圈。时间不得超过10分钟。小车运行时必须保持轨迹铁丝位于小车垂直投影之下。如有越出,每次扣2分。 (40分)
(2)实时显示小车行驶的距离和运行时间。 (10分)
(3)在任意直线段铁丝上放置4个直径约19mm的镀镍钢芯硬币(第五套人民币的1角硬币),硬币边缘紧贴铁丝,如图1所示。小车路过硬币时能够发现并发出声音提示。 (20分)
(4)尽量减少小车绕跑道跑完一圈运行时间。 (25分)
(5)其他。 ( 5分)
(6)设计报告 (20分)
项 目 主要内容 满分
方案论证 比较与选择,方案描述 3
理论分析与计算 系统相关参数设计 5
电路与程序设计 系统组成,原理框图与各部分的电路图,系统软件与流程图 5
测试方案与测试结果 测试结果完整性,测试结果分析 5
设计报告结构及规范性 摘要,正文结构规范,图表的完整与准确性 2
总 分 20
这里写图片描述

3.说明
(1)自动循迹小车允许用玩具车改装。小车用自带电池供电运行,不能使用外接电源。小车的尺寸为其在地面的投影不超过A4纸大小。小车自动运行后,不得有任何人工干预小车运动的行为,如遥控等。
(2)电感传感器除了使用TI公司配发的LDC1314芯片外,也可使用LDC1000芯片或模块,数量也仅限一只。不得使用任何其他类型的传感器用于循迹。
(3)跑道除指定的铁丝外,不得另外增加任何标记。跑道附近不应有其他额外金属物体。

直入主题:大家都知道比赛要用到的主要器件会提前通知,梁比赛之前搭好了小车并且调试好了LDC1000。然题目出来之后,我们决定采用ldc1314(因为只能用一块探测芯片,事后才发现这是一个多么错误的决定)至于小车本身我就不过多涉及,很普通的一个小车。几个重要模块:
一:电源模块
二:核心板
三:金属轨道探测模块(ldc1000或者ldc1314)
正如前面所言,比赛开始后我们放弃了调好的ldc1000改用了ldc1314,好在有ldc1000的经验,第一天我们小组做出了ldc1000的模块,也写好了相应的驱动代码。然后就开始调试小车寻迹,用了PID算法,按照P,D,I的顺序调的。途中由于用的开关电源而没有加保险管,在熬夜过程中不小心把电源接反了而烧了2576开关电源芯片(也不知道加了保险管是否真的就保险,但是后面加了保险管再也没烧过了,毕竟比赛,最好不要节外生枝)就这样在第三天早上我们调好了PID,小车能勉强走完全程完成寻迹了,心里那个激动啊,就这样我们继续修改PID参数,力求更好的效果。但第四天早上起来,不知道怎么回事把LDC1314烧了,不明不白的也不知道哪里出问题了。最悲哀就是学校老师不再给我们LDC1314。失望之后,我拿出了LDC1000,还是用ldc1000,一开始不用ldc1000是因为它只有一个通道——只能接一个线圈,而LDC1314有四个通道——能接四个线圈,所以LDC1314在寻迹上被我们理所当然的认为更好了,然而时候经过查阅datasheet和实际验证以及比赛群里的同学反映,LDC1314检测距离和灵敏度明显小于LDC1000。正式因为如此ldc’1000也是很多成功者的选择,因为ldc’1314实在是太短了,稍微数据丢失(它没有检测到)车就很容易出轨道了。从第四天开始,我们改用LDC1000——方案有二:
一:用一个线圈,利用PID来判断方向的转变(认识的一位非本校的师兄就是这样实现的),不过难点在于1,线圈要大一点,感应强度要强一些,2,小车要好控制(电机和舵机要好用)3,PID算法参数要选的非常好才行,不然很容易出轨道。
二:用两个线圈,安置在左和右用来判断方向,加上PID更可以精确一些控制。
由于我们用了直流电机(并没编码电机),其次舵机不怎么样,而且我没有好的大一点的线圈(学校老师打的PCB线圈效果极差!),担心一个线圈调不出来,所以我们采用两个线圈切换办法同样切换装置也是问题(一:用什么切换,二:切换频率对效果的影响)方案同样有二:1场管,2继电器。最终选择了继电器,频率改变小一些(的确·继电器对线圈采集的数据有一定影响,而且电流有一点变化),好在最终也算实现了。

总结几点:
一:熬夜一定要放慢动作,谨慎做事,很容易因为太困弄坏东西,得不偿失(比赛七天,前五天每天4点睡,八点起,后两天连续通宵)在很累很困的情况很容易弄错的,我们烧了1314和电源板很大原因就是太累太困又心急。
二:继电器驱动使用灌电流,不能使用拉电流(一开始怎么都驱动不了继电器,就连2003都不行,也是想不通,后来查资料找到了,卡了半天时间)
三:PID参数一定对应一个系统,系统变则参数变
四:使用SPI3的同时不能使用JTAG的复用时钟,需要关闭其复用时钟(具体我再研究研究,比赛当时使用SPI3一开始不顺利,关闭JTAG的复用时钟就ok了)
五:LDC1314和LDC1000的芯片可以改变检测的数值范围,调大差距值,但是我认为并不能改变灵敏度,而是通过调节线圈电感和连接的电容来改变灵敏度(具体可以见TI官网的在线计算工具)

最后就是一点遗憾了:第一:觉得自己准备不足,很多东西应该自己准备好的,尤其是小车,我很后悔用了一个性能太差的,直流电机(两边轮子相同电压转速还明显不一样),舵机小角度比较差,要么不转,要么转大角度。其他就是线圈我很后悔没有自己打,学校打那个确实太差,有些根本就检测不大。第二:后悔放弃LDC1000,应为LDC1314确实检测距离在我那个硬件条件太短,几乎擦着地面走,LDC1000则还要好些,几乎是两倍的距离吧,说实话一开始以为TI推销他的新出的1314就很在意这个。事实证明在硬件不太好的情况下,LDC1000还好弄一点·。第三:熬夜不要急,血的教训。

下面给出部分代码:

include

include “usart.h”

include “ldc1000.h”

include “1602.h”

include “beep.h”

include “delay.h”

include “motor.h”

include “pwm_tim5.h”

include “step_motor.h”

include “ldc_intruput.h”

include “pid.h”

extern unsigned long ProximityData; //LDC上Proximity Data
extern unsigned char flag;
extern u16 CCR3_Val , CCR4_Val ;//后轮2,3 舵机0

unsigned long red_ProximityData, bule_ProximityData;

void display(unsigned long temp,u16 adr);
void jichu_ProximityData(void);

unsigned long jichu_red,jichu_bule;
u16 time,distance;

uint8_t table[10]=”0123456789”;
uint8_t table1[10]=”Time:”;
uint8_t table2[10]=”distance:”;
extern u16 CCR3_Val;
u8 i;

int main (void)
{
NVIC_Configuration();
delay_init();
USART1_Config();
inct();
beep_Init();
SPI_LDC_Init();
TIM5_PWM_Init();
TIM7_ldc_Init(60000-1,72-1);
MOTOR_Init();
jidainqi_Init();

write_com(0x80);
delay(10);
for(i=0;i<6;i++)
write_data(table1[i]); 
write_com(0x80+0x0a);
write_data('s');
write_com(0x80+0x40);

for(i=0;i<9;i++)
write_data(table2[i]);
write_com(0x80+0x4e);
write_data(‘c’);
write_com(0x80+0x4f);
write_data(‘m’);

jichu_ProximityData();
Rear_wheel_direction(0);
while(1)
{
    if(jidianqi==0)              
    {
    LDCRead();
        if(ProximityData>9000&ProximityData<14000)
        {
                red_ProximityData=ProximityData;
        display(red_ProximityData,0x80+0x49);
        }
        else if(ProximityData<9000&ProximityData>8000)
        {
                            beep=1;
                    delay_ms(100);
                    beep=0;
        }
        else if(ProximityData<8000)
        {
            bule_ProximityData=ProximityData;

// display(bule_ProximityData,0x80+0x4F);
}
else if(ProximityData>=16000) //硬币
{
beep=1;
delay_ms(100);
beep=0;
}
delay_ms(50);
jidianqi=1;
}
else if(jidianqi==1)
{
LDCRead();
if(ProximityData>9000&ProximityData<14000)
{
red_ProximityData=ProximityData;
// display(red_ProximityData,0x80+0x49);
}
// else if(ProximityData<9000&ProximityData>8000)
// {
// beep=1;
// delay_ms(100);
// beep=0;
// }
else if(ProximityData<8000)
{
bule_ProximityData=ProximityData;
// display(bule_ProximityData,0x80+0x4F);
}
else if(ProximityData>16000) //硬币
{
beep=1;
delay_ms(100);
beep=0;
}
delay_ms(50);
jidianqi=0;
}

}
}
void display(unsigned long temp,u16 adr)
{
uint8_t i;
write_com(0x04);
delay(30);
write_com(adr);
while(temp)
{
i=temp%10;
write_data(table[i]);
temp/=10;
}
write_com(0x06);
}
void jichu_ProximityData() //获取基础值
{
u8 j;
for(j=0;j<10;j++)
{
if(jidianqi==0)
{
LDCRead();
if(ProximityData>9000&&ProximityData<18000)
{
red_ProximityData=ProximityData;
// display(red_ProximityData,0x80+0x49);
}
else if(ProximityData<9000)
{
bule_ProximityData=ProximityData;
// display(bule_ProximityData,0x80+0x4F);
}
else if(ProximityData>=18000) //硬币
{
beep=1;
delay_ms(100);
beep=0;
}
jidianqi=1;
delay_ms(100);
}
else if(jidianqi==1)
{
LDCRead();
if(ProximityData>9000&&ProximityData<18000)
{
red_ProximityData=ProximityData;
// display(red_ProximityData,0x80+0x49);
}
else if(ProximityData<9000)
{
bule_ProximityData=ProximityData;
// display(bule_ProximityData,0x80+0x4F);
}
else if(ProximityData>=18000) //硬币
{
beep=1;
delay_ms(100);
beep=0;
}
jidianqi=0;
delay_ms(100);
}
}
jichu_red=red_ProximityData;
jichu_bule=bule_ProximityData;
}

LDC1000驱动

ifndef LDC24L01_H

define LDC24L01_H

include

define GPIO_LDC GPIOC

define GPIO_LDC_CSN_Pin GPIO_Pin_5

define GPIO_LDC_CE_Pin GPIO_Pin_2

define GPIO_LDC_IQ_Pin GPIO_Pin_4

define SPI_NOP 0XFF//空指令用来读状态寄存器

/******寄存器地址区*********/

define LDC1000_CMD_REVID 0x00

define LDC1000_CMD_RPMAX 0x01

define LDC1000_CMD_RPMIN 0x02

define LDC1000_CMD_SENSORFREQ 0x03

define LDC1000_CMD_LDCCONFIG 0x04

define LDC1000_CMD_CLKCONFIG 0x05

define LDC1000_CMD_THRESHILSB 0x06

define LDC1000_CMD_THRESHIMSB 0x07

define LDC1000_CMD_THRESLOLSB 0x08

define LDC1000_CMD_THRESLOMSB 0x09

define LDC1000_CMD_INTCONFIG 0x0A

define LDC1000_CMD_PWRCONFIG 0x0B

define LDC1000_CMD_STATUS 0x20

define LDC1000_CMD_PROXLSB 0x21

define LDC1000_CMD_PROXMSB 0x22

define LDC1000_CMD_FREQCTRLSB 0x23

define LDC1000_CMD_FREQCTRMID 0x24

define LDC1000_CMD_FREQCTRMSB 0x25

// LDC BITMASKS

define LDC1000_BIT_AMPLITUDE 0x18

define LDC1000_BIT_RESPTIME 0x07

define LDC1000_BIT_CLKSEL 0x02

define LDC1000_BIT_CLKPD 0x01

define LDC1000_BIT_INTMODE 0x07

define LDC1000_BIT_PWRMODE 0x01

define LDC1000_BIT_STATUSOSC 0x80

define LDC1000_BIT_STATUSDRDYB 0x40

define LDC1000_BIT_STATUSWAKEUP 0x20

define LDC1000_BIT_STATUSCOMP 0x10

define TEST_RPMAX_MAX 0x13 /*< maximum calibration value for RPMAX /

define TEST_RPMAX_MIN 0x10 /*< minimum calibration value for RPMAX /

define TEST_RPMAX_INIT TEST_RPMAX_MIN+1 /*< RPMAX initial value /

define TEST_RPMIN_MAX 0x3D /*< maximum calibration value for RPMIN /

define TEST_RPMIN_MIN 0x3A /*< minimum calibration value for RPMIN /

define TEST_RPMIN_INIT TEST_RPMIN_MIN+1 /*< RPMIN initial value /

// Final Test Range

define TEST_RP_MSB_MAX 0x12 /*< maximum value for proximity data /

define TEST_RP_MSB_MIN 0x0A /*< minimum value for proximity data /

define TEST_FC_MAX 0x0D5D /*< maximum value for frequency counter /

define TEST_FC_MIN 0x0D39 /*< minimum value for frequency counter /

/******宏定义区*********/

define LDC_CSN_HIGH() GPIO_SetBits(GPIO_LDC, GPIO_LDC_CSN_Pin)

define LDC_CSN_LOW() GPIO_ResetBits(GPIO_LDC, GPIO_LDC_CSN_Pin) //csn置低

define LDC_Read_IRQ() GPIO_ReadInputDataBit (GPIO_LDC, GPIO_LDC_IQ_Pin)

/******函数声明区*********/
extern void SPI_LDC_Init(void);//spi的初始化
u8 SPI_LDC_RW(u8 data);
static void SPI_LDC_WriteReg(u8 reg,u8 data);//向reg寄存器中写入data
static u8 SPI_LDC_ReadReg(u8 reg);//读取指定状态寄存器的值
void LDC1000_init(void);
void LDCRead(void);
extern void MY_SPI_Init(void);
void TIM3_NVIC_Configuration(void);
static void TIM3_GPIO_Config(void);
static void TIM3_Mode_Config(void);
void TIM3_Init(void);
float CountRp(void);
unsigned long Fsensor(unsigned long lFcount);
unsigned long Fsensor(unsigned long lFcount);
unsigned long CountInductor(unsigned long lFsensor);

endif

include “ldc1000.h”

include “usart.h”

include “math.h”

define SPI_RWBIT 0x80

define Fext 32768 //32768 Hz

define ResponseTime 6144

define CapVal 0.0001 //1uF*/

unsigned long ProximityData;
unsigned long FrequencyData;
unsigned char flag;
volatile u32 speed=999;

__IO uint16_t DataRcv[5] ;

/*************初始化spi***********************
*功 能: 初始化野火的spi
*形 参: void
*返 回 值:void
*备 注:
*******************************************************/
extern void MY_SPI_Init(void)
{
SPI_InitTypeDef SPI_InitStr;
GPIO_InitTypeDef GPIO_InitStr;

/*使能GPIOB,GPIOD,复用功能时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO, ENABLE);

/*使能SPI1时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

/*对硬件stm32的SPI配置*/
/*配置 SPI_LDC_SPI的 SCK,MISO,MOSI引脚,GPIOA^5,GPIOA^6,GPIOA^7 */
GPIO_InitStr.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStr.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStr.GPIO_Mode = GPIO_Mode_AF_PP; //复用功能
GPIO_Init(GPIOA, &GPIO_InitStr);

/*对从机LDC24L01的控制角配置*/
/*配置CE引脚,GPIOA^2和 CSB 引脚*/
GPIO_InitStr.GPIO_Pin = GPIO_LDC_CSN_Pin;
GPIO_InitStr.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStr.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO_InitStr);

/*对硬件stm32的SPI配置*/
/*配置SPI_LDC_SPI的IRQ引脚,GPIOA^3*/
GPIO_InitStr.GPIO_Pin = GPIO_LDC_IQ_Pin;
GPIO_InitStr.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStr.GPIO_Mode = GPIO_Mode_IPU ;  //上拉输入
GPIO_Init(GPIOC, &GPIO_InitStr);

/* 这是自定义的宏,用于拉高csn引脚,LDC进入空闲状态 */
LDC_CSN_HIGH();

SPI_InitStr.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //双线全双工
SPI_InitStr.SPI_Mode = SPI_Mode_Master;                     //主模式
SPI_InitStr.SPI_DataSize = SPI_DataSize_8b;                 //数据大小8位
SPI_InitStr.SPI_CPOL = SPI_CPOL_High;                       //时钟极性,空闲时为低
SPI_InitStr.SPI_CPHA = SPI_CPHA_2Edge;                      //第1个边沿有效,上升沿为采样时刻
SPI_InitStr.SPI_NSS = SPI_NSS_Soft;                         //NSS信号由软件产生
SPI_InitStr.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;  //8分频,9MHz
SPI_InitStr.SPI_FirstBit = SPI_FirstBit_MSB;                //高位在前
SPI_InitStr.SPI_CRCPolynomial = 7;                          //CRC校验复位
SPI_Init(SPI1, &SPI_InitStr);

/* Enable SPI1  */
SPI_Cmd(SPI1, ENABLE);

}

/*************向LDC中读/写一个字节*************
*功 能: 向LDC中读/写一个字节
*形 参: 写入的数据
*返 回 值: 读取得的数据
*备 注:
*******************************************************/
u8 SPI_LDC_RW(u8 data) //向LDC中读写一个字节
{
/* 当 SPI发送缓冲器非空时等待 */
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);

/* 通过 SPI2发送一字节数据 */
SPI_I2S_SendData(SPI1, data);

 /* 当SPI接收缓冲器为空时等待 */
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);

/* Return the byte read from the SPI bus */
return SPI_I2S_ReceiveData(SPI1);

}

/*************向LDC指定的寄存器写值*************
*功 能: 向LDC指定的寄存器写值
*形 参: reg:LDC的命令+寄存器地址。
* data:将要向寄存器写入的数据
*返 回 值: 寄存器的状态
*备 注:
*******************************************************/
static void SPI_LDC_WriteReg(u8 reg,u8 data)
{

// LDC_CE_LOW();//进入待机模式1,低功耗模式,此模式下LDC可以接收数据
LDC_CSN_LOW();//拉低csn片选信号,使能LDC的spi传输

SPI_LDC_RW(reg);//向LDC发送命令和寄存器的号

SPI_LDC_RW(data);//向刚才指定的寄存器写入数据

LDC_CSN_HIGH();//拉高csn片选信号,即释放LDC的spi传输完毕;

}

/*************读取LDC指定的寄存器值*************
*功 能: 读取LDC指定的寄存器值
*形 参: reg:LDC寄存器地址。
*返 回 值: 状态寄存器的数据
*备 注:
*******************************************************/
static u8 SPI_LDC_ReadReg(u8 reg)
{
u8 Reg_Value;

// LDC_CE_LOW();//进入待机模式1,低功耗模式,此模式下LDC可以接收数据
LDC_CSN_LOW();//拉低csn片选信号,使能LDC的spi传输

SPI_LDC_RW(reg|SPI_RWBIT);//选择寄存器
Reg_Value = SPI_LDC_RW(SPI_NOP);

LDC_CSN_HIGH();//拉高csn片选信号,即释放LDC的spi传输完毕;

return Reg_Value;

}

/**********************************************************
* @brief: LDC1000初始化配置,ps:在SPI中配置了数据位16个数据长度,故
* 在发送数据时可以将地址和值进行或运算一起发送出去
* @param: none
* @return: none
***********************************************************/
void LDC1000_init(void)
{
// SPI_Write(LDC1000_CMD_RPMAX<<8|0xff);
SPI_LDC_WriteReg(LDC1000_CMD_RPMAX,0x31); //配置Rp_MAX(0x01)寄存器
SPI_LDC_WriteReg(LDC1000_CMD_RPMIN,0x1b); //配置Rp_MIN(0x02)寄存器
SPI_LDC_WriteReg(LDC1000_CMD_SENSORFREQ,0x94); //配置Sensor Frequency(0x03)寄存器
SPI_LDC_WriteReg(LDC1000_CMD_LDCCONFIG,0x17); //配置LDC Configuration(0x04)寄存器
SPI_LDC_WriteReg(LDC1000_CMD_CLKCONFIG,0x00); //配置Clock Configuration(0x05)寄存器,
//使用TBCLK作为时钟源 //配置INTB为比较输出标志位(status of Comparator output)
SPI_LDC_WriteReg(LDC1000_CMD_THRESHILSB,0x50); //配置Comparator Threshold High(0x06)寄存器低8位
SPI_LDC_WriteReg(LDC1000_CMD_THRESHIMSB,0x14); //配置Comparator Threshold High(0x07)寄存器高8位
SPI_LDC_WriteReg(LDC1000_CMD_THRESLOLSB,0xC0); //配置Comparator Threshold Low(0x08)寄存器低8位
SPI_LDC_WriteReg(LDC1000_CMD_INTCONFIG,0x02); //配置INTB Pin Configuration(0x0A),
SPI_LDC_WriteReg(LDC1000_CMD_PWRCONFIG,0x01); //配置Power Configuration(0x0B)寄存器, //为Active Mode,使能转化
}

/**********************************************************
* @brief: 使用SPI读取LDC1000中的数据
* @param: none
* @return: none
***********************************************************/
void LDCRead(void)
{
// LDC_CSN_LOW();
ProximityData = 0;
FrequencyData = 0;
while(LDC_Read_IRQ()!=0)
printf(“read 1 failed!”);
DataRcv[0] = SPI_LDC_ReadReg(LDC1000_CMD_PROXLSB); //写入将要读取的Proximity Data LSB寄存器地址(0x21)
//printf(“0 %d\r\n”,DataRcv[0]);
//SPI_Read(&DataRcv[0]); //读取上述寄存器中的值,并存入DataRcv[0]
ProximityData|= DataRcv[0] ;
while(LDC_Read_IRQ()!=0)
printf(“read 2 failed!”);
DataRcv[1] = SPI_LDC_ReadReg(LDC1000_CMD_PROXMSB); //写入将要读取的Proximity Data MSB寄存器地址(0x22)
//printf(“1 %d\r\n”,DataRcv[1]);
//SPI_Read(&DataRcv[1]); //读取上述寄存器中的值,并存入DataRcv[1]
ProximityData|= (DataRcv[1]<<8) ; //组合成ProximityData
while(LDC_Read_IRQ()!=0)
printf(“read 3 failed!”);
DataRcv[2] = SPI_LDC_ReadReg(LDC1000_CMD_FREQCTRLSB); //写入将要读取的Frequency Counter Data LSB寄存器地址(0x23)
//printf(“2 %d\r\n”,DataRcv[2]);
//SPI_Read(&DataRcv[2]); //读取上述寄存器中的值,并存入DataRcv[2]
FrequencyData|= DataRcv[2] ;
while(LDC_Read_IRQ()!=0)
printf(“read 4 failed!”);
DataRcv[3] = SPI_LDC_ReadReg(LDC1000_CMD_FREQCTRMID); //写入将要读取的Frequency Counter Data Mid-Byte寄存器地址(0x24)
//printf(“3 %d\r\n”,DataRcv[3]);
//SPI_Read(&DataRcv[3]); //读取上述寄存器中的值,并存入DataRcv[3]
FrequencyData|= (DataRcv[3]<<8) ;
while(LDC_Read_IRQ()!=0);
DataRcv[4] = SPI_LDC_ReadReg(LDC1000_CMD_FREQCTRMSB); //写入将要读取的Frequency Counter Data MSB寄存器地址(0x25)
//printf(“4 %d\r\n\n\n”,DataRcv[4]);
//SPI_Read(&DataRcv[4]); //读取上述寄存器中的值,并存入DataRcv[4]
FrequencyData|= (DataRcv[4]<<16) ; //组合成FrequencyData

// LDC_CSN_HIGH();
}
//——————————————————//
//———————-Rp 计算————————-//
//————-unsigned long CountRp() —————–//
//——————————————————//
float CountRp(void)
{
float Y;
unsigned Code;
float Rp;

Code =ProximityData;

Y = ((float)Code/32768.0);
printf(“Y value: %f\r\n”,Y);
Rp = (float)(((float)TEST_RPMAX_MAX*(float)TEST_RPMAX_MIN) / ((float)TEST_RPMAX_MIN*(1-Y)+(float)TEST_RPMAX_MAX*(float)Y));

return Rp;
}

//——————————————————//
//——————-LC震荡频率求值——————–//
//—–unsigned long Fsensor(unsigned long lFcount)—–//、
//输入参数:lFcount: Fre Code的值
//——————————————————//
unsigned long Fsensor(unsigned long lFcount)
{
unsigned long lFsensor;
unsigned long Fcount;

Fcount = lFcount;
lFsensor = (1*Fext*ResponseTime)/(3*Fcount);

return lFsensor;
}
//——————————————————//
//———————L电感求值———————-//
//–unsigned long CountInductor(unsigned long lFsensor)-//
//输入参数:lFsensor: LC谐振频率
//——————————————————//
unsigned long CountInductor(unsigned long lFsensor)
{
unsigned long Fsensor;
unsigned long L;

Fsensor = lFsensor;

L = (unsigned long)(pow(10,12)* 1/(CapVal * pow(2*3.14*Fsensor,2)) ); //uH

return L;
}
extern void SPI_LDC_Init(void)
{
TIM3_Init();
MY_SPI_Init();
LDC1000_init();
flag=1;
}

/*
* 函数名:TIM3_NVIC_Configuration
* 描述 :TIM3中断优先级配置
* 输入 :无
* 输出 :无
*/
void TIM3_NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);                                                     
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;   
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

}

static void TIM3_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOB, &GPIO_InitStructure);

}

static void TIM3_Mode_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;

/* PWM信号电平跳变值 */
u16 TIM_CCR3_Val = 2;  

/* -----------------------------------------------------------------------
TIME3 可以输出 4 路 PWM 波形:
TIME3_CH1   ------  PA6
TIME3_CH2   ------  PA7
TIME3_CH3   ------  PB0
TIME3_CH4   ------  PB1
----------------------------------------------------------------------- */

/* Time base configuration */        
TIM_TimeBaseStructure.TIM_Period = 3;       //当定时器从0计数到999,即为1000次,为一个定时周期
TIM_TimeBaseStructure.TIM_Prescaler = 0;        //设置预分频:预分频72,即为1KHz
TIM_TimeBaseStructure.TIM_ClockDivision = 0;    //设置时钟分频系数:不分频
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //向上计数模式

TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_ClearFlag(TIM3, TIM_FLAG_Update);                                       /* 清除溢出中断标志 */
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);

/* PWM1 Mode configuration: Channel3 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;       //配置为PWM模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;   
TIM_OCInitStructure.TIM_Pulse = TIM_CCR3_Val;      //设置跳变值,当计数器计数到这个值时,电平发生跳变
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;  //当定时器计数值小于CCR1_Val时为高电平

TIM_OC3Init(TIM3, &TIM_OCInitStructure);     //使能通道1

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;       //配置为PWM模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;   
TIM_OCInitStructure.TIM_Pulse = TIM_CCR3_Val;      //设置跳变值,当计数器计数到这个值时,电平发生跳变
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;  //当定时器计数值小于CCR1_Val时为高电平

TIM_OC4Init(TIM3, &TIM_OCInitStructure);     //使能通道1

TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);    //使用CCR3寄存器的影子寄存器(直到产生更新事件才发生更改)

//TIM_ARRPreloadConfig(TIM3, ENABLE);            // 使能TIM3重载寄存器ARR

/* TIM3 enable counter */
TIM_Cmd(TIM3, ENABLE);                   //使能定时器3

}

void TIM3_Init(void)
{
//TIM3_NVIC_Configuration();
TIM3_GPIO_Config();
TIM3_Mode_Config();
}

由于本人并不擅长PID,就不粘贴PID了,而且·PID和具体系统有关。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/133868.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 你也可以成为VTuber

    你也可以成为VTuber

  • mysql 修改 表名 列名 为小写

    mysql 修改 表名 列名 为小写表名改为小写SELECTCONCAT(‘ALTERTABLE’,table_name,’RENAME’,LOWER(table_name),”;”)ASstatementFROMinformation_schema.TABLESWHEREtable_schema=’数据库’ANDtable_nameLIKE’表名%’;列名改为小写SELECTconcat(‘altertable’,TABLE_…

  • java snmp walk,SNMPWALK 用法详解

    java snmp walk,SNMPWALK 用法详解(1)Net-SNMPSNMPWALK(1)NAMEsnmpwalk-communicateswithanetworkentityusingSNMPGETNEXTrequests.SYNOPSISsnmpwalk[APPL…

  • android刘海屏适配(刘海屏或圆角适配)

    安卓P版本也就是刚发布的安卓9.0其中就加入了刘海屏相关的API。其相关行为与功能变更也是非常多的,从其变更的趋势及功能来看,google在进一步的收紧权限。其P版本变更行为中就加入了对非SDK接口使用的新限制。无论是直接,通过反射还是通过JNI。只要应用程序引用非SDK接口或尝试使用反射或JNI获取其句柄,就会应用这些限制。通常,应用程序应仅使用SDK中类的官方记录部分。特别是,这意味着…

  • 计算机三级-数据库技术

    计算机三级-数据库技术三级数据库技术知识点总结1数据字典是对系统种各类数据描述的集合,包括数据项,数据结构,数据流,数据存储和处理过程五个部分2数据模型的三要素:数据结构、数据操作和完整性约束3数据库系统:一般由数据库、操作系统、数据库管理系统(及其工具)、应用系统、数据库管理人员和用户构成4数据模型:数据模型是数据库系统的数学形式框架,是数据库系统的核心和基础5数据模型的分类:概念模型,也称信息…

  • 桌面太单调?一起用Python做个自定义动态壁纸,竟然还可以放视频!「建议收藏」

    桌面太单调?一起用Python做个自定义动态壁纸,竟然还可以放视频!「建议收藏」前言前段时间,用PyQt5写了几篇文章,关于Python自制一款炫酷音乐播放器、自定义桌面动画挂件、车牌自动识别系统。今天就继续给大家分享一个实战案例,带大家一起用Python的PyQt5开发一个自定义动态桌面壁纸,好玩又有趣!首先一起来看看最终实现的自定义动态壁纸效果:…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号