打印
[STM32F4]

月末了,分享个lcd的电子指针式时钟挺酷的。

[复制链接]
4072|51
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 一路向北lm 于 2017-11-27 22:50 编辑

指针式时钟走时很准,在LCD上效果不错。

实验现象.jpg (79.69 KB )

实验现象.jpg

gui.rar

5.54 KB

lcd.rar

2.92 KB

RTC.rar

1.17 KB

沙发
一路向北lm|  楼主 | 2017-11-27 22:54 | 只看该作者
首先是RTC部分的底层驱动
1.打开电源时钟
2.打开存储器时钟
3.使能或者失能RTC和后备寄存器访问
4.将外设BKP的全部寄存器重设为缺省值
5.设置外部低速晶振(LSE)
6.检查指定的RCC标志位设置与否
7.设置RTC时钟(RTCCLK)
8.使能或者失能RTC时钟
9.等待RTC寄存器同步
10.等待最近一次对RTC寄存器的写操作完成
11.使能或者失能指定的RTC中断
12.等待最近一次对RTC寄存器的写操作完成
13./设置预分频 使用外部晶振为32.768K,要想1s中断则预分频数设置为32767,系统会在此数字基础上加1
14.等待最近一次对RTC寄存器的写操作完成






使用特权

评论回复
板凳
一路向北lm|  楼主 | 2017-11-27 22:54 | 只看该作者
RTC初始化具体代码如下
void rtc_init()
{
           NVIC_InitTypeDef NVIC_InitStructure;

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);//
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);//

        PWR_BackupAccessCmd(ENABLE);//
        BKP_DeInit();//
        RCC_LSEConfig(RCC_LSE_ON);//
        while(RCC_GetFlagStatus(RCC_FLAG_LSERDY)==RESET);//
        RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);//
        RCC_RTCCLKCmd(ENABLE);//
        RTC_WaitForSynchro(); //
        RTC_WaitForLastTask();//
        RTC_ITConfig(RTC_IT_SEC,ENABLE);//
        RTC_WaitForLastTask();//
        RTC_SetPrescaler(32767);/
        RTC_WaitForLastTask();//
       

        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
        NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
       
               
}

使用特权

评论回复
地板
玛尼玛尼哄| | 2017-11-28 10:03 | 只看该作者
表盘是怎么绘制的,看看。

使用特权

评论回复
5
一路向北lm|  楼主 | 2017-11-28 11:42 | 只看该作者
玛尼玛尼哄 发表于 2017-11-28 10:03
表盘是怎么绘制的,看看。

等下会给gui

使用特权

评论回复
6
dongnanxibei| | 2017-11-28 11:51 | 只看该作者
分享了个好玩的,感谢感谢。

使用特权

评论回复
7
一路向北lm|  楼主 | 2017-11-28 12:00 | 只看该作者
时钟初始化
void clockinit_RTC()
{
        if(BKP_ReadBackupRegister(BKP_DR1)!=0XA5A5)//从指定的后备寄存器中读出数据
        {
                //第一次运行  初始化设置
                //RTC初始化
                rtc_init();
                RTC_WaitForLastTask();//等待最近一次对RTC寄存器的写操作完成
                RTC_SetCounter(0x9326);//设置RTC计数器的值 10:27:50
                RTC_WaitForLastTask();
                BKP_WriteBackupRegister(BKP_DR1,0xA5A5);
        }
        else
        {       
                RTC_WaitForSynchro();//等待RTC寄存器同步       
                RTC_WaitForLastTask();//等待写RTC寄存器完成               
            RTC_ITConfig(RTC_IT_SEC,ENABLE);//使能RTC秒中断   
                RTC_WaitForLastTask();//等待写RTC寄存器完成       
        }
        RCC_ClearFlag();//清除复位标志;               
}

使用特权

评论回复
8
一路向北lm|  楼主 | 2017-11-28 12:03 | 只看该作者
下面是LCD屏幕的驱动
01.lcd屏幕管脚驱动  初始化TFT的IO口
void TFT_GPIO_Config(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
       
        /* 打开时钟使能 */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE  
                              | RCC_APB2Periph_GPIOG, ENABLE);

        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_12;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        /* FSMC_A10(G12) 和RS(G0)*/
        GPIO_Init(GPIOG, &GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4
                                      | GPIO_Pin_5 | GPIO_Pin_8 | GPIO_Pin_8
                                                                  | GPIO_Pin_9 | GPIO_Pin_10 |GPIO_Pin_11
                                                                  | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14
                                                                  | GPIO_Pin_15 );

        GPIO_Init(GPIOD, &GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9
                                       | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12
                                                                   | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15);

        GPIO_Init(GPIOE, &GPIO_InitStructure);
}

使用特权

评论回复
9
一路向北lm|  楼主 | 2017-11-28 12:04 | 只看该作者
毫无疑问下一步肯定是FSMC的配置 虽然很长要懂得每一步的配置过程。已经加注释
初始化FSMC
void TFT_FSMC_Config(void)
{
        /* 初始化函数 */
        FSMC_NORSRAMInitTypeDef        FSMC_NORSRAMInitStructure;
        FSMC_NORSRAMTimingInitTypeDef  FSMC_NORSRAMTiming;

        /* 设置读写时序,给FSMC_NORSRAMInitStructure调用 */
        /* 地址建立时间,3个HCLK周期 */
        FSMC_NORSRAMTiming.FSMC_AddressSetupTime = 0x02;

        /* 地址保持时间,1个HCLK周期 */
        FSMC_NORSRAMTiming.FSMC_AddressHoldTime = 0x00;

        /* 数据建立时间,6个HCLK周期 */
        FSMC_NORSRAMTiming.FSMC_DataSetupTime = 0x05;

        /* 数据保持时间,1个HCLK周期 */
        FSMC_NORSRAMTiming.FSMC_DataLatency = 0x00;

        /* 总线恢复时间设置 */
        FSMC_NORSRAMTiming.FSMC_BusTurnAroundDuration = 0x00;
       
        /* 时钟分频设置 */
        FSMC_NORSRAMTiming.FSMC_CLKDivision = 0x01;

        /* 设置模式,如果在地址/数据不复用时,ABCD模式都区别不大 */
        FSMC_NORSRAMTiming.FSMC_AccessMode = FSMC_AccessMode_B;

        /*设置FSMC_NORSRAMInitStructure的数据*/
        /* FSMC有四个存储块(bank),我们使用第一个(bank1) */
        /* 同时我们使用的是bank里面的第 4个RAM区 */
        FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM4;

        /* 这里我们使用SRAM模式 */
        FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;

        /* 使用的数据宽度为16位 */
        FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;

        /* 设置写使能打开 */
        FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;

        /* 选择拓展模式使能,即设置读和写用不同的时序 */
        FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Enable;
       
        /* 设置地址和数据复用使能不打开 */
        FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
       
        /* 设置读写时序 */
        FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &FSMC_NORSRAMTiming;
       
        /* 设置写时序 */
        FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &FSMC_NORSRAMTiming;

        /* 打开FSMC的时钟 */
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);
         
        FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);

        /*!< Enable FSMC Bank1_SRAM Bank */
        FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM4, ENABLE);       
}

使用特权

评论回复
10
一路向北lm|  楼主 | 2017-11-28 12:08 | 只看该作者
TFT lcd写操作,如果是对TFT的操作,必定要往TFT写入数据,下面是对TFT的基本写操作   写入的16位命令与 写入的16位数据 大家要区分开来。
写入的16位命令
void TFT_WriteCmd(uint16_t cmd)
{
        TFT->TFT_CMD = cmd<<8 ;
}
写入的16位数据
void TFT_WriteData(u16 dat)
{
        TFT->TFT_DATA = dat<<8;
}

void TFT_WriteData_Color(u16 color)
{
        TFT->TFT_DATA = color&0xff00;
        TFT->TFT_DATA = color<<8;
}

使用特权

评论回复
11
一路向北lm|  楼主 | 2017-11-28 12:11 | 只看该作者
接着就是激动地时刻,初始化TFT屏幕了,这一部分完成就可以操作我们的TFT屏幕了(开心)
初始化很长,大家会调用即可,感兴趣可参考手册研究下。
初始化LCD屏
void TFT_Init(void)
{
        uint16_t i;

        TFT_GPIO_Config();
        TFT_FSMC_Config();

        //************* Start Initial Sequence **********//       
        TFT_WriteCmd(0xCB);  
        TFT_WriteData(0x39);
        TFT_WriteData(0x2C);
        TFT_WriteData(0x00);
        TFT_WriteData(0x34);  
        TFT_WriteData(0x02);   

        TFT_WriteCmd(0xCF);  
        TFT_WriteData (0x00);
        TFT_WriteData (0xa2); //c1
        TFT_WriteData (0Xf0);  //30
         
        TFT_WriteCmd(0xE8);  
        TFT_WriteData (0x84);          //85
        TFT_WriteData (0x11);          //00
        TFT_WriteData (0x7a);          //79
       
       
        TFT_WriteCmd(0xEA);  
        TFT_WriteData (0x66);  //00
        TFT_WriteData (0x00);
       
        TFT_WriteCmd(0xED);  
        TFT_WriteData (0x55);         //64
        TFT_WriteData (0x01);         //03
        TFT_WriteData (0X23);         //12
        TFT_WriteData (0X01);         //81
         
        TFT_WriteCmd(0xF7);  
        TFT_WriteData (0x20);         //20
       
       
        TFT_WriteCmd(0xC0);    //Power control
        TFT_WriteData (0x1c);   //VRH[5:0]         //1c
         
        TFT_WriteCmd(0xC1);    //Power control
        TFT_WriteData (0x13);   //SAP[2:0];BT[3:0]         //13
         
        TFT_WriteCmd(0xC5);    //VCM control
        TFT_WriteData (0x23);
        TFT_WriteData (0x3F);
         
        TFT_WriteCmd(0xC7);    //VCM control2
        TFT_WriteData(0xA5);
       
        TFT_WriteCmd(0xB1);  
        TFT_WriteData (0x00);
        TFT_WriteData (0x17);
       
        TFT_WriteCmd(0x3A);  
        TFT_WriteData (0x55);
       
        TFT_WriteCmd(0xB6);  
        TFT_WriteData (0x0A);
        TFT_WriteData (0xa2);  //a2
        TFT_WriteData (0x27);
        TFT_WriteData (0x00);
         
        TFT_WriteCmd(0x36);    // Memory Access Control
        TFT_WriteData (0x08);           //08        BGR
         
        TFT_WriteCmd(0xF2);    // 3Gamma Function Disable
        TFT_WriteData (0x02);         //00
         
        TFT_WriteCmd(0x26);    //Gamma curve selected
        TFT_WriteData (0x01);
         
        TFT_WriteCmd(0xE0);    //Set Gamma
        TFT_WriteData (0x0F);
        TFT_WriteData (0x14);
        TFT_WriteData (0x13);
        TFT_WriteData (0x0C);
        TFT_WriteData (0x0E);
        TFT_WriteData (0x05);
        TFT_WriteData (0x45);
        TFT_WriteData (0x85);
        TFT_WriteData (0x36);
        TFT_WriteData (0x09);
        TFT_WriteData (0x14);
        TFT_WriteData (0x05);
        TFT_WriteData (0x09);
        TFT_WriteData (0x03);
        TFT_WriteData (0x00);
         
        TFT_WriteCmd(0XE1);    //Set Gamma
        TFT_WriteData (0x00);
        TFT_WriteData (0x24);
        TFT_WriteData (0x26);
        TFT_WriteData (0x03);
        TFT_WriteData (0x0F);
        TFT_WriteData (0x04);
        TFT_WriteData (0x3F);
        TFT_WriteData (0x14);
        TFT_WriteData (0x52);
        TFT_WriteData (0x04);
        TFT_WriteData (0x10);
        TFT_WriteData (0x0E);
        TFT_WriteData (0x38);
        TFT_WriteData (0x39);
        TFT_WriteData (0x0F);

        TFT_WriteCmd(0x2A );
        TFT_WriteData(0x00);
        TFT_WriteData(0x00);
        TFT_WriteData(0x00);
        TFT_WriteData(0xEF);

        TFT_WriteCmd(0x2B );
        TFT_WriteData(0x00);
        TFT_WriteData(0x00);
        TFT_WriteData(0x01);
        TFT_WriteData(0x3F);
         
        TFT_WriteCmd(0x11);    //Exit Sleep
        for(i=50000; i>0; i--);         //延时
        for(i=50000; i>0; i--);
        for(i=50000; i>0; i--);
        for(i=50000; i>0; i--);
        for(i=50000; i>0; i--);
        for(i=50000; i>0; i--);
        TFT_WriteCmd(0x29);    //Display on

}

使用特权

评论回复
12
一路向北lm|  楼主 | 2017-11-28 12:12 | 只看该作者
午饭到了,该休息了,晚上接着更新。

使用特权

评论回复
13
一路向北lm|  楼主 | 2017-11-28 22:35 | 只看该作者
设置要操作的窗口范围
这个函数有三个参数,我们只要会调用,利用好参数就行。
三个参数  1.xStart:窗口起始X坐标
             2. yStart:窗口起始Y坐标
             3. xEnd:窗口结束X坐标
void TFT_SetWindow(uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd)
{
        TFT_WriteCmd(0x2A);

    TFT_WriteData(xStart/256);
    TFT_WriteData(xStart%256);
    TFT_WriteData(xEnd/256);
    TFT_WriteData(xEnd%256);

    TFT_WriteCmd(0x2b);
    TFT_WriteData(yStart/256);
    TFT_WriteData(yStart%256);
    TFT_WriteData(yEnd/256);
    TFT_WriteData(yEnd%256);
    TFT_WriteCmd(0x2c);
}

使用特权

评论回复
14
一路向北lm|  楼主 | 2017-11-28 23:03 | 只看该作者
将LCD清屏成相应的颜色
最后就是清屏这一步了。          
void TFT_ClearScreen(uint16_t color)
{
        uint16_t i, j ;

        TFT_SetWindow(0, 0, TFT_XMAX, TFT_YMAX);         //作用区域
          for(i=0; i<TFT_XMAX+1; i++)
        {
                for (j=0; j<TFT_YMAX+1; j++)
                {
                        TFT_WriteData_Color(color);
                }
       

使用特权

评论回复
15
liuchangyin| | 2017-11-29 10:38 | 只看该作者
效果不错

使用特权

评论回复
16
一路向北lm|  楼主 | 2017-11-29 11:49 | 只看该作者
接下来可以对TFT进行操作了。

使用特权

评论回复
17
一路向北lm|  楼主 | 2017-11-29 12:04 | 只看该作者
进入GUI部分
在彩屏上面画一点
void GUI_Dot(uint16_t x, uint16_t y, uint16_t color)
{  
        TFT_SetWindow(x, y, x, y);  //设置点的位置
        TFT_WriteData_Color(color);       //画点       
}

void GUI_Line(u16 xStart, u16 yStart, u16 xEnd, u16 yEnd, u16 color)
{
        u16 t;  
        int xerr = 0, yerr = 0, delta_x, delta_y, distance;  
        int incx, incy;  
        u16 row, col;  
        delta_x = xEnd - xStart;//计算坐标增量  
        delta_y = yEnd - yStart;  
        col = xStart;  
        row = yStart;  
        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++)  
        {                                     //画线输出  
            GUI_Dot(col, row, color);
            xerr += delta_x;  
            yerr += delta_y;  
                  if(xerr > distance)  
            {  
                xerr -= distance;  
                col += incx;  
            }  
            if(yerr > distance)  
            {  
                yerr -= distance;  
                row += incy;  
            }  
        }  
}

使用特权

评论回复
18
一路向北lm|  楼主 | 2017-11-29 12:07 | 只看该作者
参数如下    利用好参数即可。      
x:点的X坐标
y:点的Y坐标
color:点的颜色

使用特权

评论回复
19
一路向北lm|  楼主 | 2017-11-29 12:10 | 只看该作者
有了画点的函数我们可以在局部涂上颜色
给一个区域涂上颜色
void GUI_Box(uint16_t xState, uint16_t yState, uint16_t xEnd, uint16_t yEnd, uint16_t color)
{
        uint16_t temp;

    if((xState > xEnd) || (yState > yEnd))
    {
        return;
    }   
        TFT_SetWindow(xState, yState, xEnd, yEnd);
    xState = xEnd - xState + 1;
        yState = yEnd - yState + 1;

        while(xState--)
        {
                 temp = yState;
                while (temp--)
                 {       
                        TFT_WriteData_Color(color);
                }
        }
}

使用特权

评论回复
20
一路向北lm|  楼主 | 2017-11-29 12:10 | 只看该作者
上面的参数:
sx:起始X坐标, sy:其实Y坐标,
ex:终止X坐标, ey:终止Y坐标,
color:方框的颜色

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

275

主题

3784

帖子

76

粉丝