c语言 表盘指针旋转,请教下,表盘指针图片旋转 ??

, 0, 0 );

}

_ClockParm->hMem1_ClockDest = GUI_MEMDEV_CreateFixed32( 18, 28+79,  // 最终显示的 x,y 地址

_ClockPosStream[0].xSize,           // 与显示最大表盘尺寸宽度一致即可

_ClockPosStream[0].ySize );

_ClockParm->hMem1_ClockLcd = GUI_MEMDEV_CreateFixed32( 18, 28+79,   // 最终显示的 x,y 地址

_ClockPosStream[0].xSize,           // 与显示最大表盘尺寸宽度一致即可

_ClockPosStream[0].ySize );

//-----------------------------------------------------------------------------------------

GUI_MEMDEV_Select(0);

GUI_MEMDEV_CopyFromLCD( _ClockParm->hMem1_ClockLcd );                  // 将 LCD 内容复制到存储设备

// 释放申请内存

for( i=0; i<4; i++ )

{

_ClockParm->_acComBuff = _ClockParm->_acClockBuf;

myFree( SRAMEX, (void *) _ClockParm->_acComBuff);                // 使用完后释放内存

}

//        myFree( SRAMEX,(void *) _ClockParm );  // 这个 _ClockParm 参数不能够释放,因为程序一直在运行

/* 配置回之前选择的目标窗口 */

//        WM_SelectWindow( hWinOld );

}

/*******************************************************************************

*函数名称        : Clock_DrawDisp

*功能描述        : 更新时钟表盘

*输入参数        : 无

*输出参数        : 无

*返 回 值        : 无

-------------------------------------------------------------------------------*/

void Clock_DrawDisp(void)

{

int      t0;   // 用于三个指针的计数

int      t1;

int      t2;

// 时间与日期需要同时获取,切记切记,

RTC_GetTime();

RTC_GetDate();

t0 = 360 - (g_tRTC.Sec * 6);                                    // 第一个指针计数,用于旋转秒针 (6度/秒,顺时针方向换算成逆时针方向)

t1 = 360 - (g_tRTC.Min *6) -(g_tRTC.Sec /10);          // 第二个指针计数,用于旋转分针. 秒针每移动10秒,分钟移动的角度为1度

/*------------------------------------------------------------------------

g_tRTC.Hour%12 是把 24 小时制式转化为 12 小时制,*30是因为时针每小时运行 30 度,

((sTime.Minutes /10)*5) 这句是分钟每移动10分钟,小时时针移动 5 度

--------------------------------------------------------------------------*/

t2 = 360 - (((g_tRTC.Hour)%12) * 30) - ((g_tRTC.Min /10)*5);

GUI_MEMDEV_Select( _ClockParm->hMem1_ClockDest );

GUI_MEMDEV_Write( _ClockParm->hMem1_ClockLcd );          // 将给定存储设备的内容写入当前选定的存储设备中,

// 即hMem1_ClockLcd -> hMem1_ClockDest

StreamBitmapDisp( "0:/ICON/Clock_Icon/bk_blue2.dta", 0, 28 );

//        GUI_BMP_ShowBkPicture();                 // 使用 emwin  v5.40 ABGR 版本,需要在此处重新绘制一下背景色,否则表盘不会显示透明功能

// 如果使用单色背景色,则此处不需要,但需要吧 GUI_CreateBitmapFromStream 此函数

// 之前屏蔽的函数打开即可,切记切记  2018.07.05  sws

GUI_MEMDEV_Rotate( _ClockParm->hMem1_Clock[0], _ClockParm->hMem1_ClockDest,

0,                  // 显示地址由 hMemDest、hMemLcd 决定

0,                  // 显示地址由 hMemDest、hMemLcd 决定

0,                  // 因为显示表盘不需要旋转,所以此次的值为0

1000);

GUI_MEMDEV_Rotate( _ClockParm->hMem1_Clock[1], _ClockParm->hMem1_ClockDest,

147-15,                 // 显示时针计算方法,表盘的中心x坐标 - 时针的中心x坐标,偏移量

// 已经在创建时设定好的,也就是以创建时的坐标为基准

147-34,

t2 * 1000,

1000 );

GUI_MEMDEV_Rotate( _ClockParm->hMem1_Clock[2], _ClockParm->hMem1_ClockDest,

147-9,

147-57,

t1 * 1000,

1000 );

GUI_MEMDEV_Rotate( _ClockParm->hMem1_Clock[3], _ClockParm->hMem1_ClockDest,

147-5,

147-78,

t0 * 1000,

1000 );

GUI_MEMDEV_Select(0);

GUI_MULTIBUF_Begin();

GUI_MEMDEV_CopyToLCD( _ClockParm->hMem1_ClockDest );        // 将内容显示到 LCD 屏幕上

GUI_MULTIBUF_End();

}

/*-------------- 对话框资源列表 ---------------------------------*/

// 特别注意:对话框资源列表的第一个控件必须是框架窗口或者窗口,其它的控件都不可以是第一个

static const GUI_WIDGET_CREATE_INFO _aDialogCreateRTC[] =

{

{ WINDOW_CreateIndirect, "Window",        ID_WINDOW_0,        0,  28,  800, 452, 0, 0x0, 0 },

{ TEXT_CreateIndirect,      "日期", GUI_ID_TEXT0, 270,  60, 200,  20, 0,0},

{ TEXT_CreateIndirect,      "时间", GUI_ID_TEXT1, 420,  60, 200,  20, 0,0},

{ TEXT_CreateIndirect,      "星期", GUI_ID_TEXT2, 270,  80, 200,  20, 0,0},

{ TEXT_CreateIndirect,      "闹钟", GUI_ID_TEXT3, 420,  80, 200,  20, 0,0},

{ BUTTON_CreateIndirect, "DlgBack", ID_BUTTON_0,  691,   5,  100,  56, 0, 0, 0 },        // 返回按钮

{ BUTTON_CreateIndirect, "TimeSet", ID_BUTTON_1,    0, 390,  134,  62, 0, 0, 0 },        // 时间设置按钮

};

/*******************************************************************************

*函数名称        : _cbButtonBack

*功能描述        : “返回”按钮回调函数         ID_BUTTON_0

*输入参数        : *pMsg  消息指针

*输出参数        : 无

*返 回 值        : 无

-------------------------------------------------------------------------------*/

static void _cbButtonBack( WM_MESSAGE * pMsg )

{

WM_HWIN          hWin;

hWin  = pMsg->hWin;

switch ( pMsg->MsgId )

{

case WM_PAINT:

if ( BUTTON_IsPressed( hWin ))

{

StreamBitmapDisp("0:/ICON/Clock_Icon/clock_back_d.dta", 0, 0 );

}

else

{

StreamBitmapDisp("0:/ICON/Clock_Icon/clock_back_u.dta", 0, 0 );

}

break;

default:

BUTTON_Callback( pMsg );

}

}

/*******************************************************************************

*函数名称        : _cbButtonSet

*功能描述        : “时间设置”按钮回调函数         ID_BUTTON_1

*输入参数        : *pMsg  消息指针

*输出参数        : 无

*返 回 值        : 无

-------------------------------------------------------------------------------*/

static void _cbButtonSet( WM_MESSAGE * pMsg )

{

WM_HWIN  hWin;

hWin  = pMsg->hWin;

switch ( pMsg->MsgId )

{

case WM_PAINT:

if( BUTTON_IsPressed( hWin ))

{

GUI_SetAlpha( 0xB0 );

StreamBitmapDisp( "0:/ICON/Clock_Icon/clock_set1.dta", 0, 0 );

GUI_SetAlpha( 0 );

}

else

{

StreamBitmapDisp( "0:/ICON/Clock_Icon/clock_set1.dta", 0, 0 );

}

break;

default:

BUTTON_Callback( pMsg );

}

}

/*******************************************************************************

*函数名称        : Clock_Update

*功能描述        : 更新时间

*输入参数        : *pMsg  消息指针变量

*输出参数        : 无

*返 回 值        : 无

-------------------------------------------------------------------------------*/

static void Clock_Update( WM_MESSAGE *pMsg )

{

char                 buf[30];

WM_HWIN         hWin = pMsg->hWin;

RTC_GetTime();

RTC_GetDate();

RTC_GetAlarmA();

/* 更新时间 */

sprintf( buf, "时间: %0.2d:%0.2d:%0.2d ", g_tRTC.Hour, g_tRTC.Min, g_tRTC.Sec );

TEXT_SetText( WM_GetDialogItem( hWin, GUI_ID_TEXT1 ), buf );

/* 更新日期 */

sprintf( buf, "日期: %0.4d/%0.2d/%0.2d", g_tRTC.Year, g_tRTC.Mon, g_tRTC.Day );

TEXT_SetText( WM_GetDialogItem( hWin, GUI_ID_TEXT0 ), buf );

/* 更新星期 */

sprintf( buf, "星期: %s", ucWeekDay[g_tRTC.Week-1]);

TEXT_SetText( WM_GetDialogItem( hWin, GUI_ID_TEXT2 ), buf );

/* 更新闹钟 */

sprintf( buf, "闹钟: %0.2d:%0.2d:%0.2d ", g_tAlarm.Hour, g_tAlarm.Min, g_tAlarm.Sec );

TEXT_SetText( WM_GetDialogItem( hWin, GUI_ID_TEXT3 ), buf );

}

/*******************************************************************************

*函数名称        : InitDialogRTC

*功能描述        : 时钟对话框回调函数中的初始化消息

*输入参数        : *pMsg  消息指针变量

*输出参数        : 无

*返 回 值        : 无

-------------------------------------------------------------------------------*/

static void InitDialogRTC( WM_MESSAGE * pMsg )

{

WM_HWIN         hWin = pMsg->hWin;

WM_HWIN         hItem;

WM_CreateTimer( WM_GetClientWindow( hWin ), // 接受信息的窗口的句柄

0,                                      // 用户定义的Id。如果不对同一窗口使用多个定时器,此值可以设置为零

10,                               // 周期,此周期过后指定窗口应收到消息

0 );                                                         // 留待将来使用,应为0

hItem = WM_GetDialogItem( pMsg->hWin, ID_BUTTON_0 );        // “返回”

WM_SetHasTrans( hItem );

WM_SetCallback( hItem, _cbButtonBack );

hItem = WM_GetDialogItem( pMsg->hWin, ID_BUTTON_1 );        // “时钟设置”

WM_SetHasTrans( hItem );

WM_SetCallback( hItem, _cbButtonSet );

TEXT_SetFont( WM_GetDialogItem( hWin, GUI_ID_TEXT0 ), &GUI_FontHZHT16 );        // "日期"

TEXT_SetFont( WM_GetDialogItem( hWin, GUI_ID_TEXT1 ), &GUI_FontHZHT16 );        // "时间"

TEXT_SetFont( WM_GetDialogItem( hWin, GUI_ID_TEXT2 ), &GUI_FontHZHT16 );        // "星期"

TEXT_SetFont( WM_GetDialogItem( hWin, GUI_ID_TEXT3 ), &GUI_FontHZHT16 );        // "闹钟"

GUI_MEMDEV_RTC_ClockInit();

}

/*******************************************************************************

*函数名称        : _cbCallbackRTC

*功能描述        : 回调函数

*输入参数        : *pMsg  消息指针变量

*输出参数        : 无

*返 回 值        : 无

-------------------------------------------------------------------------------*/

static void _cbCallbackRTC( WM_MESSAGE * pMsg )

{

int                 NCode, Id;

WM_HWIN         hWin = pMsg->hWin;

GUI_RECT         rRTC = {18, 28+79, 294+18-1, 294+28+79-1};

switch ( pMsg->MsgId )

{

case WM_PRE_PAINT:                        // WM_PAINT 消息发出前,WM 将此消息发送到窗口

/*--------------------------------------------------------------

一般的内存设备动画函数不使用多重缓冲。但在某些情况下,启用多个缓冲区是有意义的。

如果启用动画函数在显示器上绘制内存设备之前 / 之后使用 GUI_MULTIBUF_Begin() 和

GUI_MULTIBUF_Begin()。

-----------------------------------------------------------------*/

GUI_MULTIBUF_Begin();

break;

case WM_PAINT:

{

GUI_SetBkColor( GUI_BLACK );

GUI_Clear();

StreamBitmapDisp( "0:/ICON/Clock_Icon/bk_blue2.dta", 0, 0 );         // 背景

Clock_DrawDisp();                // 更新时钟表盘

break;

}

case WM_POST_PAINT:                        // WM_PAINT 消息处理后,WM 立即将此消息发送到窗口

/*--------------------------------------------------------------

一般的内存设备动画函数不使用多重缓冲。但在某些情况下,启用多个缓冲区是有意义的。

如果启用动画函数在显示器上绘制内存设备之前 / 之后使用 GUI_MULTIBUF_Begin() 和

GUI_MULTIBUF_Begin()。

-----------------------------------------------------------------*/

GUI_MULTIBUF_End();

break;

case WM_TIMER:                                // 定时1ms更新一次时间

WM_InvalidateRect( hWin, &rRTC );                // 使窗口的指定矩形区域无效

Clock_Update( pMsg );                                        // 更新时间

WM_RestartTimer( pMsg->Data.v, 1000 );        // 重新启动定时器

break;

case WM_INIT_DIALOG:

InitDialogRTC( pMsg );        // 时钟对话框回调函数中的初始化消息

break;

case WM_KEY:

switch (((WM_KEY_INFO*)(pMsg->Data.p))->Key )

{

case GUI_KEY_ESCAPE:

GUI_EndDialog( hWin, 1 );

break;

case GUI_KEY_ENTER:

GUI_EndDialog( hWin, 0 );

break;

}

break;

case WM_NOTIFY_PARENT:

Id = WM_GetId( pMsg->hWinSrc );

NCode = pMsg->Data.v;

switch ( Id )

{

case ID_BUTTON_0:        // "返回"按钮,此例子未使用

switch( NCode )

{

case WM_NOTIFICATION_CLICKED:

//GUI_EndDialog( hWin, 0);

break;

}

break;

case ID_BUTTON_1:        // "时间设置"

switch( NCode )

{

case WM_NOTIFICATION_CLICKED:

App_SetTimeAlarm();                        // 创建设置时间/闹钟对话框

break;

}

break;

}

break;

default:

WM_DefaultProc( pMsg );

}

}

/*******************************************************************************

*函数名称        : MainTask_Calendar01

*功能描述        : 时钟GUI主函数

*输入参数        : 无

*输出参数        : 无

*返 回 值        : 无

-------------------------------------------------------------------------------*/

void MainTask_Calendar01(void)

{

GUI_CURSOR_Show();

GUI_SetBkColor( GUI_BLACK );

GUI_Clear();

// 创建时钟对话框

GUI_CreateDialogBox( _aDialogCreateRTC, GUI_COUNTOF(_aDialogCreateRTC), &_cbCallbackRTC, 0, 0, 0 );

while(1)

{

GUI_Delay(10);

}

}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个简单的基于STM32的TFTLCD屏幕滚动显示的代码示例,以SPI接口为例,你可以根据自己的具体情况进行修改: ```c #include "stm32f4xx.h" #include "stm32f4xx_spi.h" #define LCD_WIDTH 240 #define LCD_HEIGHT 320 uint16_t buffer1[LCD_WIDTH * LCD_HEIGHT]; // 缓冲区1 uint16_t buffer2[LCD_WIDTH * LCD_HEIGHT]; // 缓冲区2 uint16_t *pDisplayBuffer; // 当前显示的缓冲区指针 uint16_t *pUpdateBuffer; // 即将更新的缓冲区指针 void LCD_Init(void) { // 初始化TFTLCD屏幕 // ... } void DMA_Config(void) { DMA_InitTypeDef DMA_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); // 打开DMA时钟 DMA_InitStructure.DMA_Channel = DMA_Channel_3; // 选择DMA通道3 DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(SPI1->DR); // 设置外设地址为SPI1数据寄存器 DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)pUpdateBuffer; // 设置内存地址为即将更新的缓冲区 DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; // 设置数据传输方向为内存到外设 DMA_InitStructure.DMA_BufferSize = LCD_WIDTH * LCD_HEIGHT; // 设置数据传输大小 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 禁用外设地址增量模式 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // 启用内存地址增量模式 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // 设置外设数据大小为半字 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; // 设置内存数据大小为半字 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; // 设置DMA传输模式为普通模式 DMA_InitStructure.DMA_Priority = DMA_Priority_High; // 设置DMA传输优先级为高 DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; // 禁用FIFO模式 DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; // 设置FIFO阈值为半满 DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; // 设置内存突发传输为单次传输 DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; // 设置外设突发传输为单次传输 DMA_Init(DMA2_Stream3, &DMA_InitStructure); // 初始化DMA } void LCD_Update(void) { pUpdateBuffer = (pDisplayBuffer == buffer1) ? buffer2 : buffer1; // 切换即将更新的缓冲区 // 将要更新的缓冲区的内容更新为要显示的内容 // ... DMA_Cmd(DMA2_Stream3, DISABLE); // 关闭DMA DMA_SetCurrDataCounter(DMA2_Stream3, LCD_WIDTH * LCD_HEIGHT); // 设置DMA传输数据量 DMA_MemoryTargetConfig(DMA2_Stream3, (uint32_t)pUpdateBuffer, DMA_Memory_0); // 设置DMA内存地址 DMA_Cmd(DMA2_Stream3, ENABLE); // 启动DMA // 等待DMA传输完成 while (DMA_GetFlagStatus(DMA2_Stream3, DMA_FLAG_TCIF3) == RESET); // 切换当前显示的缓冲区 pDisplayBuffer = pUpdateBuffer; } int main(void) { LCD_Init(); // 初始化TFTLCD屏幕 DMA_Config(); // 配置DMA pDisplayBuffer = buffer1; pUpdateBuffer = buffer2; while(1) { LCD_Update(); // 更新TFTLCD屏幕 } } ``` 在以上示例代码中,DMA配置使用了STM32的标准库函数,你也可以使用HAL库或者LL库进行配置。另外,需要根据具体的TFTLCD屏幕型号和接口类型进行相应的修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值