基于STM32F103的悬挂运动控制系统项目总结
扫描二维码
随时随地手机看文章
这个是暑假期间为了准备2013电子设计竞赛做的一个小项目,其实就是2005电子竞赛的E题。。今天抽出时间在此总结一下,,顺便也可以和大家分享一下思路。。
关于这道题的要求,我就不多说了,大家都可以百度到。。我们做的悬挂系统有一下四个功能:
1、让悬挂物体走直线。
2、让悬挂物体画圆。
3、在TFT屏上设定坐标并让悬挂物从原点走到该坐标。
4、在TFT屏上触摸一点显示出该点坐标并使悬挂物从原点运动到该坐标。
下面首先说说画直线的思路:将起点和终点的坐标作为函数的传递参数。通过计算起点和终点到两个滑轮之间的距离差可以算出两个电机在这段时间转过的距离。。因为时间是相同的,所以令两个电机的速度比等于通过计算得到的距离比即可。。
接下来说说画圆的思路:画圆可以近似为画一个正四百边形(五百、六百……都可以,可以试试哪种效果最好)。把画圆分四次,一次画四分之一个圆,就相当于正一百边形的四分之一。。然后通过简单的数学运算算出下一时刻的坐标,然后把当前坐标赋值为下一时刻坐标,这两步之间延一下时,防止值没有传递过去。具体代码如下:
for(i=1; i<100; i++)
//第一象限
{
now_x1 = x0 + Circle_rx*i;
now_y1 = sqrt( r*r - (Circle_rx*i)*(Circle_rx*i) ) + y0;
Draw_Line( now_x0, now_y0, now_x1, now_y1);
Delay_ms(30);
now_x0 = now_x1;
now_y0 = now_y1;
x = now_x1;
y = now_y1;
}
其中now_x0 、now_y0表示当前时刻坐标, now_x1、now_y1表示下一时刻坐标。
在然后就是设定坐标,调用STM32开发板光盘例程里面的TFT.c文件里面的函数,即可显示在TFT屏上面显示出坐标。然后通过32单片机自带的按键控制即可。最后调用画直线的函数将原点坐标和通过TFT屏设定的坐标分别作为起点和终点坐标即可。
之后就是第四个,触屏点的实现,使用TFT屏上面自带的ADS7843这个4线电阻触摸屏转换接口芯片,这是一款具有同步串行接口的12位取样模数转换器。然后些整个触摸控制IC的驱动程序存放在TOUCH.c文件里面:驱动步骤如下:首先写出对触摸控制IC的读写程序,然后读取触摸点的电压值,然后滤波采样,采样后去平均值减小误差。
具体驱动程序如下:
*****************************************************************************
// 实现功能:
ADS7843启动
*****************************************************************************/
void start_7843(void)
{
GPIO_ResetBits(GPIOC, GPIO_Pin_8); //TPCLK置低
GPIO_SetBits(GPIOC, GPIO_Pin_9); //TPCS置高
GPIO_SetBits(GPIOA, GPIO_Pin_8); //TPDI置高
GPIO_SetBits(GPIOC, GPIO_Pin_8); //TPCLK置高
GPIO_ResetBits(GPIOC, GPIO_Pin_9); //TPCS置低
}
/*****************************************************************************
// 实现功能:
写8位命令到触摸控制IC
// 输入参数: temp 需要写入的8位控制命令
*****************************************************************************/
void Write_7843(uchar temp)
//SPI写8位命令到触摸控制IC
{
uchar i=0;
for(i=0;i<8;i++) //循环8次写入一字节
{
if(temp&0x80)
GPIO_SetBits(GPIOA, GPIO_Pin_8); //TPDI置高
else
GPIO_ResetBits(GPIOA, GPIO_Pin_8);
//判断最高位是否为1,为1则向数据位写1
GPIO_ResetBits(GPIOC, GPIO_Pin_8);
delay(1);
//送一个脉冲,上升沿有效,将DIN位数据送入到IC
GPIO_SetBits(GPIOC, GPIO_Pin_8);
delay(1);
temp<<=1;
//待写数据左移1位,准备好写下一位数据
}
}
/*****************************************************************************
// 实现功能:
从触摸控制IC读8位数据到控制器
// 返回参数: temp 需要写入的8位控制命令
*****************************************************************************/
uint Read_7843(void)
//SPI 读数据
{
uchar i=0;
uint temp=0;
for(i=0;i<12;i++)
//循环12次读取12位结果
{
temp<<=1;
//temp左移一位,准备读取下一位
GPIO_SetBits(GPIOC, GPIO_Pin_8);
delay(1);
//下降沿有效
GPIO_ResetBits(GPIOC, GPIO_Pin_8);
delay(1);
if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_11))
temp++;
//判断控制IC送出的一位数据是否为1,如果为1,赋给temp的最低位
}
return(temp); //返回结果
}
/*****************************************************************************
// 实现功能:读取触摸点X轴和Y轴电压值
// 返回参数:pix 读取到的触摸点电压值
*****************************************************************************/
struct struct1 AD7843()
{
struct struct1 pix;
GPIO_ResetBits(GPIOC, GPIO_Pin_9);
Write_7843(0x90); //送控制字 10010000 即用差分方式读X坐标,详细请见有关资料
GPIO_SetBits(GPIOC, GPIO_Pin_8);
delay(1);
GPIO_ResetBits(GPIOC, GPIO_Pin_8);
delay(1);
pix.y=Read_7843();
Write_7843(0xD0); //送控制字 11010000 即用差分方式读Y坐标 详细请见有关资料
GPIO_SetBits(GPIOC, GPIO_Pin_8);
delay(1);
GPIO_ResetBits(GPIOC, GPIO_Pin_8);
delay(1);
pix.x=Read_7843();
GPIO_SetBits(GPIOC, GPIO_Pin_9);
return pix;
}
/*****************************************************************************
// 实现功能:软件滤波,滤掉波动过大的采样点
// 返回参数:flag 采集数据是否有效标志,flag=1;则数据有效
*****************************************************************************/
uchar pix_filter(struct struct1 pix1,struct struct1 pix2)
{
uchar flag=0;
int x=pix1.x>pix2.x?pix1.x-pix2.x:pix2.x-pix1.x; //X轴两次采样绝对值
int y=pix1.y>pix2.y?pix1.y-pix2.y:pix2.y-pix1.y; //Y轴两次采样绝对值
if(x<10&&y<10)
//软件滤波,2次取样的值相差太大的视为噪声
{
flag=1;
coordinate.x=(pix1.x+pix2.x)/2; //求两次采样平均值
coordinate.y=(pix1.y+pix2.y)/2;
}
return flag;
}
/*****************************************************************************
// 实现功能:读取采集结果,两次取均值
*****************************************************************************/
uchar Getpix(void) //取采样值,此处使用软件滤波,2次取样的值相差太大的视为噪声
{
uchar flag=0;
struct struct1 pix1;
struct struct1 pix2;
if (GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_12)==0)
{
pix1=AD7843();
pix2=AD7843();
if(pix_filter(pix1,pix2)==1) //得到当前TP的取样值,此处使用软件滤波,2次取样的值相差太大的视为噪声
{
if((coordinate.x>Xmin)&&(coordinate.y>Ymin))
{
lx=(uint)(240.0*(coordinate.x-Xmin)/(Xmax-Xmin)); //坐标转换,即根据采样值计算实际坐标值
ly=(uint)(320.0*(coordinate.y-Ymin)/(Ymax-Ymin)); //Xmin、max和Ymin、Ymax分别是触摸屏横纵坐标的最小/最大值
flag=1;
}
}
}
return flag;
}
以上就是我的总结,,希望对大家有所帮助。。也希望自己继续努力。。加油!Fighting