基于战舰STM32开发板的模拟时钟开发
最近闲得无聊,在公司属于实习期,老板也不给活干,手上刚好有个STM32的开发板子,就想随便写点小东西,经人提醒,写个钟吧,
LCD的驱动以及相关函数战舰都给我们了 直接用就好,有空可以看看具体驱动怎么写的,感觉写驱动也好好玩的样子。
伪代码如下
lcd_init();
各种初始化;
LCD_Clear(WHITE);
清屏为白色(背景色);
dorw_rang(120,160,100,1000);
画圆圈,画矩形,画刻度等;
显示时钟的框架;
while(1)
{
POINT_COCLOR=WHITE;
画笔和背景一样颜色,清除上一秒时分秒针的痕迹;
s_angle=(2*Pi/60)*(s-1)-Pi/2;//极坐标角度
sx=(int)80*cos(s_angle)+120;//极坐标换为x
sy=(int)80*sin(s_angle)+160;//极坐标换为y
dorw_line(120,160,hx,hy);//画和背景色一样的秒针,目的在于消除上一秒的显示,
同理画出时分针
POINT_COLOR=BLACK;
画笔换黑色,画下当前时分秒针;
s_angle=(2*Pi/60)*s-Pi/2;
sx=(int)80*cos(s_angle)+120;
sy=(int)80*sin(s_angle)+160;
dorw_line(120,160,sx,sy);
delay_ms(1000);//延时一秒 秒++
s++;
}
总结,因为是自己写着玩,就没有做具体中断时钟,用系统tk时钟延时一秒得了,
然后画斜线dorw_line()和画圆dorw_rang()是我自己编的算法,后来也找到网上别人的算法,LCD_DrawLine()和Draw_Circle(),大家可以对比看一看;
然后界面不好看,需要优化,然后lcd分辨率太低,斜线不好看,或者是我斜线的算法不对。
附上画线和画圆函数
//画线
//x1,y1:起点坐标
//x2,y2:终点坐标
void LCD_DrawLine(u16 x1, u16 y1, u16 x2, u16 y2)
{
u16 t;
int xerr=0,yerr=0,delta_x,delta_y,distance;
int incx,incy,uRow,uCol;
delta_x=x2-x1; //计算坐标增量
delta_y=y2-y1;
uRow=x1;
uCol=y1;
if(delta_x>0)incx=1; //设置单步方向
else if(delta_x==0)incx=0;//垂直线
else {incx=-1;delta_x=-delta_x;}
if(delta_y>0)incy=1;
else if(delta_y==0)incy=0;//水平线
else{incy=-1;delta_y=-delta_y;}
if( delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴
else distance=delta_y;
for(t=0;t<=distance+1;t++ )//画线输出
{
LCD_DrawPoint(uRow,uCol);//画点
xerr+=delta_x ;
yerr+=delta_y ;
if(xerr>distance)
{
xerr-=distance;
uRow+=incx;
}
if(yerr>distance)
{
yerr-=distance;
uCol+=incy;
}
}
}
//在指定位置画一个指定大小的圆
//(x,y):中心点
//r :半径
void Draw_Circle(u16 x0,u16 y0,u8 r)
{
int a,b;
int di;
a=0;b=r;
di=3-(r<<1); //判断下个点位置的标志
while(a<=b)
{
LCD_DrawPoint(x0+a,y0-b); //5
LCD_DrawPoint(x0+b,y0-a); //0
LCD_DrawPoint(x0+b,y0+a); //4
LCD_DrawPoint(x0+a,y0+b); //6
LCD_DrawPoint(x0-a,y0+b); //1
LCD_DrawPoint(x0-b,y0+a);
LCD_DrawPoint(x0-a,y0-b); //2
LCD_DrawPoint(x0-b,y0-a); //7
a++;
//使用Bresenham算法画圆
if(di<0)di +=4*a+6;
else
{
di+=10+4*(a-b);
b--;
}
}
}
/*********画圆圈函数******
**x,y1为圆心坐标,r为半径**
**参数t为圆圈的点速,因为**
**是用极坐标方法画的,t代**
**表将圆周长分为多少个点画**
**出来**********************/
void dorw_rang(u16 x,u16 y,u16 r,u16 t)
{
int xx,yy;
for(i=0;i
fabs(x2-x1))
c=fabs(y2-y1);//c为比较长边,这样才能保证另一边点数够
else
c=fabs(x2-x1);
if(fabs(y2-y1)>fabs(x2-x1))
{
if(y2>y1) q=y1;//q为较小坐标,
else q=y2;
}
else
{
if(x2>x1) q=x1;
else q=x2;
}
for(i=0;ifabs(x2-x1))
{
x=(int)((q-z)/k);//构建二元一次方程,y=kx+z,已知一个值,求出另一个值,
y=(int)q;
q++;
}
else
{
x=(int)q;
y=(int)((k*q)+z);
q++;
}
LCD_DrawPoint(x,y);
}
}
}
}