1 /******************************************************************************************************************************************
2 * 文件名称: SWM341_lcd.c
3 * 功能说明: SWM341单片机的LCD功能驱动库
4 * 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1
5 * 注意事项:
6 * 版本日期: V1.1.0 2017年10月25日
7 * 升级记录:
8 *
9 *
10 *******************************************************************************************************************************************
11 * @attention
12 *
13 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS WITH CODING INFORMATION
14 * REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. AS A RESULT, SYNWIT SHALL NOT BE HELD LIABLE
15 * FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
16 * OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION CONTAINED HEREIN IN CONN-
17 * -ECTION WITH THEIR PRODUCTS.
18 *
19 * COPYRIGHT 2012 Synwit Technology
20 *******************************************************************************************************************************************/
21 #include "SWM341.h"
22 #include "SWM341_lcd.h"
23
24 #include <string.h>
25
26
27 /******************************************************************************************************************************************
28 * 函数名称: LCD_Init()
29 * 功能说明: LCD初始化
30 * 输 入: LCD_TypeDef * LCDx 指定要被设置的LCD,有效值包括LCD
31 * LCD_InitStructure * initStruct 包含LCD相关设定值的结构体
32 * 输 出: 无
33 * 注意事项: 无
34 ******************************************************************************************************************************************/
LCD_Init(LCD_TypeDef * LCDx,LCD_InitStructure * initStruct)35 void LCD_Init(LCD_TypeDef * LCDx, LCD_InitStructure * initStruct)
36 {
37 switch((uint32_t)LCDx)
38 {
39 case ((uint32_t)LCD):
40 SYS->CLKEN0 |= (0x01 << SYS_CLKEN0_LCD_Pos);
41 break;
42 }
43
44 LCDx->CR = ((initStruct->ClkDiv - 2) << LCD_CR_CLKDIV_Pos) |
45 (initStruct->SampleEdge << LCD_CR_CLKINV_Pos) |
46 (1 << LCD_CR_CLKALW_Pos) |
47 ((initStruct->Format & 1) << LCD_CR_FORMAT_Pos) |
48 ((initStruct->Format >> 1) << LCD_CR_SEREN_Pos) |
49 (1 << LCD_CR_BURSTEN_Pos) |
50 (1 << LCD_CR_BURSTLEN_Pos) |
51 ((1-initStruct->IntEOTEn) << LCD_CR_AUTORESTA_Pos);
52
53 LCDx->CRH = ((initStruct->HsyncWidth - 1) << LCD_CRH_HSW_Pos) |
54 ((initStruct->Hbp - 1) << LCD_CRH_HBP_Pos) |
55 ((initStruct->HnPixel - 1) << LCD_CRH_PIX_Pos) |
56 ((initStruct->Hfp - 1) << LCD_CRH_HFP_Pos);
57
58 LCDx->CRV = ((initStruct->VsyncWidth - 1) << LCD_CRV_VSW_Pos) |
59 ((initStruct->Vbp - 1) << LCD_CRV_VBP_Pos) |
60 ((initStruct->VnPixel - 1) << LCD_CRV_PIX_Pos) |
61 ((initStruct->Vfp - 1) << LCD_CRV_VFP_Pos);
62
63 LCDx->BGC = initStruct->Background;
64
65 LCDx->L[0].LCR = (1 << LCD_LCR_EN_Pos) |
66 (0 << LCD_LCR_CKEN_Pos) |
67 (0xFF << LCD_LCR_ALPHA_Pos);
68
69 LCDx->L[0].WHP = (0 << LCD_WHP_STA_Pos) |
70 ((initStruct->HnPixel - 1) << LCD_WHP_STP_Pos);
71
72 LCDx->L[0].WVP = (0 << LCD_WVP_STA_Pos) |
73 ((initStruct->VnPixel - 1) << LCD_WVP_STP_Pos);
74
75 LCDx->L[0].ADDR = initStruct->DataSource;
76
77 LCDx->L[0].LLEN = (initStruct->HnPixel - 1);
78
79 LCDx->IF = 1; //清除标志
80 LCDx->IE = initStruct->IntEOTEn;
81
82 switch((uint32_t)LCDx)
83 {
84 case ((uint32_t)LCD):
85 if(initStruct->IntEOTEn) NVIC_EnableIRQ(LCD_IRQn);
86 break;
87 }
88 }
89
90 /******************************************************************************************************************************************
91 * 函数名称: LCD_LayerInit()
92 * 功能说明: LCD层初始化
93 * 输 入: LCD_TypeDef * LCDx 指定要被设置的LCD,有效值包括LCD
94 * uint32_t layerx 要初始化的LCD层,取值LCD_LAYER_1、LCD_LAYER_2
95 * LCD_LayerInitStructure * initStruct 包含LCD层相关设定值的结构体
96 * 输 出: 无
97 * 注意事项: 无
98 ******************************************************************************************************************************************/
LCD_LayerInit(LCD_TypeDef * LCDx,uint32_t layerx,LCD_LayerInitStructure * initStruct)99 void LCD_LayerInit(LCD_TypeDef * LCDx, uint32_t layerx, LCD_LayerInitStructure * initStruct)
100 {
101 LCDx->L[layerx].LCR = (1 << LCD_LCR_EN_Pos) |
102 (0 << LCD_LCR_CKEN_Pos) |
103 (initStruct->Alpha << LCD_LCR_ALPHA_Pos);
104
105 LCDx->L[layerx].WHP = (initStruct->HStart << LCD_WHP_STA_Pos) |
106 (initStruct->HStop << LCD_WHP_STP_Pos);
107
108 LCDx->L[layerx].WVP = (initStruct->VStart << LCD_WVP_STA_Pos) |
109 (initStruct->VStop << LCD_WVP_STP_Pos);
110
111 LCDx->L[layerx].ADDR = initStruct->DataSource;
112
113 LCDx->L[layerx].LLEN = (initStruct->HStop - initStruct->HStart);
114
115 LCD->CR |= (1 << LCD_CR_VBPRELOAD_Pos);
116 }
117
118 /******************************************************************************************************************************************
119 * 函数名称: LCD_SetLayerPos()
120 * 功能说明: LCD层位置设定
121 * 输 入: LCD_TypeDef * LCDx 指定要被设置的LCD,有效值包括LCD
122 * uint32_t layerx 要设置的LCD层,取值LCD_LAYER_1、LCD_LAYER_2
123 * uint16_t hstart, uint16_t hstop, uint16_t vstart, uint16_t vstop,详细说明见 LCD_LayerInitStructure
124 * 输 出: 无
125 * 注意事项: 无
126 ******************************************************************************************************************************************/
LCD_SetLayerPos(LCD_TypeDef * LCDx,uint32_t layerx,uint16_t hstart,uint16_t hstop,uint16_t vstart,uint16_t vstop)127 void LCD_SetLayerPos(LCD_TypeDef * LCDx, uint32_t layerx, uint16_t hstart, uint16_t hstop, uint16_t vstart, uint16_t vstop)
128 {
129 LCDx->L[layerx].WHP = (hstart << LCD_WHP_STA_Pos) |
130 (hstop << LCD_WHP_STP_Pos);
131
132 LCDx->L[layerx].WVP = (vstart << LCD_WVP_STA_Pos) |
133 (vstop << LCD_WVP_STP_Pos);
134
135 LCD->CR |= (1 << LCD_CR_VBPRELOAD_Pos);
136 }
137
138 /******************************************************************************************************************************************
139 * 函数名称: LCD_Start()
140 * 功能说明: 启动一次数据传输
141 * 输 入: LCD_TypeDef * LCDx 指定要被设置的LCD,有效值包括LCD
142 * 输 出: 无
143 * 注意事项: 无
144 ******************************************************************************************************************************************/
LCD_Start(LCD_TypeDef * LCDx)145 void LCD_Start(LCD_TypeDef * LCDx)
146 {
147 LCDx->START |= (1 << LCD_START_GO_Pos);
148 }
149
150 /******************************************************************************************************************************************
151 * 函数名称: LCD_IsBusy()
152 * 功能说明: 是否正在进行数据传输
153 * 输 入: LCD_TypeDef * LCDx 指定要被设置的LCD,有效值包括LCD
154 * 输 出: uint32_t 1 正在传输数据 0 数据传输已完成
155 * 注意事项: 无
156 ******************************************************************************************************************************************/
LCD_IsBusy(LCD_TypeDef * LCDx)157 uint32_t LCD_IsBusy(LCD_TypeDef * LCDx)
158 {
159 return (LCDx->START & LCD_START_GO_Msk) ? 1 : 0;
160 }
161
162 /******************************************************************************************************************************************
163 * 函数名称: LCD_INTEn()
164 * 功能说明: LCD中断使能,完成指定长度的数据传输时触发中断
165 * 输 入: LCD_TypeDef * LCDx 指定要被设置的LCD,有效值包括LCD
166 * 输 出: 无
167 * 注意事项: 无
168 ******************************************************************************************************************************************/
LCD_INTEn(LCD_TypeDef * LCDx)169 void LCD_INTEn(LCD_TypeDef * LCDx)
170 {
171 LCDx->IE = 1;
172 }
173
174 /******************************************************************************************************************************************
175 * 函数名称: LCD_INTDis()
176 * 功能说明: LCD中断禁止,完成指定长度的数据传输时不触发中断
177 * 输 入: LCD_TypeDef * LCDx 指定要被设置的LCD,有效值包括LCD
178 * 输 出: 无
179 * 注意事项: 无
180 ******************************************************************************************************************************************/
LCD_INTDis(LCD_TypeDef * LCDx)181 void LCD_INTDis(LCD_TypeDef * LCDx)
182 {
183 LCDx->IE = 0;
184 }
185
186 /******************************************************************************************************************************************
187 * 函数名称: LCD_INTClr()
188 * 功能说明: LCD中断标志清除
189 * 输 入: LCD_TypeDef * LCDx 指定要被设置的LCD,有效值包括LCD
190 * 输 出: 无
191 * 注意事项: 无
192 ******************************************************************************************************************************************/
LCD_INTClr(LCD_TypeDef * LCDx)193 void LCD_INTClr(LCD_TypeDef * LCDx)
194 {
195 LCDx->IF = 1;
196 }
197
198 /******************************************************************************************************************************************
199 * 函数名称: LCD_INTStat()
200 * 功能说明: LCD中断状态查询
201 * 输 入: LCD_TypeDef * LCDx 指定要被设置的LCD,有效值包括LCD
202 * 输 出: uint32_t 0 未完成指定长度的数据传输 非0 完成指定长度的数据传输
203 * 注意事项: 无
204 ******************************************************************************************************************************************/
LCD_INTStat(LCD_TypeDef * LCDx)205 uint32_t LCD_INTStat(LCD_TypeDef * LCDx)
206 {
207 return (LCDx->IF & 1);
208 }
209
210
211 /******************************************************************************************************************************************
212 * 函数名称: MPULCD_Init()
213 * 功能说明: MPU LCD初始化
214 * 输 入: LCD_TypeDef * LCDx 指定要被设置的LCD,有效值包括LCD
215 * MPULCD_InitStructure * initStruct 包含MPU LCD相关设定值的结构体
216 * 输 出: 无
217 * 注意事项: 无
218 ******************************************************************************************************************************************/
MPULCD_Init(LCD_TypeDef * LCDx,MPULCD_InitStructure * initStruct)219 void MPULCD_Init(LCD_TypeDef * LCDx, MPULCD_InitStructure * initStruct)
220 {
221 switch((uint32_t)LCDx)
222 {
223 case ((uint32_t)LCD):
224 SYS->CLKEN0 |= (0x01 << SYS_CLKEN0_LCD_Pos);
225 __NOP();__NOP();__NOP();
226 break;
227 }
228
229 LCDx->CR = (1 << LCD_CR_MPUEN_Pos) |
230 (LCD_FMT_RGB565 << LCD_CR_FORMAT_Pos); //MPU模式只支持RGB565
231
232 LCDx->L[0].LCR |= (1 << LCD_LCR_EN_Pos); //MPU模式下需要使能Layer1
233
234 LCDx->MPUCR = ((initStruct->RDHoldTime - 1) << LCD_MPUCR_RDHOLD_Pos) |
235 ((initStruct->WRHoldTime - 1) << LCD_MPUCR_WRHOLD_Pos) |
236 ((initStruct->CSFall_WRFall - 1) << LCD_MPUCR_CS0WR0_Pos) |
237 ((initStruct->WRRise_CSRise - 1) << LCD_MPUCR_WR1CS1_Pos) |
238 ((initStruct->RDCSRise_Fall - 1) << LCD_MPUCR_RCS1_0_Pos) |
239 ((initStruct->WRCSRise_Fall - 1) << LCD_MPUCR_WCS1_0_Pos);
240 }
241
LCD_WR_REG(LCD_TypeDef * LCDx,uint16_t reg)242 void LCD_WR_REG(LCD_TypeDef * LCDx, uint16_t reg)
243 {
244 LCDx->MPUIR = reg;
245 while(LCD_IsBusy(LCDx)) __NOP();
246 }
247
LCD_WR_DATA(LCD_TypeDef * LCDx,uint16_t val)248 void LCD_WR_DATA(LCD_TypeDef * LCDx, uint16_t val)
249 {
250 LCDx->MPUDR = val;
251 while(LCD_IsBusy(LCDx)) __NOP();
252 }
253
LCD_WriteReg(LCD_TypeDef * LCDx,uint16_t reg,uint16_t val)254 void LCD_WriteReg(LCD_TypeDef * LCDx, uint16_t reg, uint16_t val)
255 {
256 LCDx->MPUIR = reg;
257 while(LCD_IsBusy(LCDx)) __NOP();
258
259 LCDx->MPUDR = val;
260 while(LCD_IsBusy(LCDx)) __NOP();
261 }
262
LCD_ReadReg(LCD_TypeDef * LCDx,uint16_t reg)263 uint16_t LCD_ReadReg(LCD_TypeDef * LCDx, uint16_t reg)
264 {
265 LCDx->MPUIR = reg;
266 while(LCD_IsBusy(LCDx)) __NOP();
267
268 return LCDx->MPUDR;
269 }
270
271 /******************************************************************************************************************************************
272 * 函数名称: MPULCD_DMAStart()
273 * 功能说明: MPU LCD DMA搬运显示数据
274 * 输 入: LCD_TypeDef * LCDx 指定要被设置的LCD,有效值包括LCD
275 * uint32_t * buff 要搬运的显示数据
276 * uint16_t hpix 横向像素数,即每行像素数,必须是偶数
277 * uint16_t vpix 纵向像素数,即行数
278 * 输 出: 无
279 * 注意事项: 无
280 ******************************************************************************************************************************************/
MPULCD_DMAStart(LCD_TypeDef * LCDx,uint32_t * buff,uint16_t hpix,uint16_t vpix)281 void MPULCD_DMAStart(LCD_TypeDef * LCDx, uint32_t * buff, uint16_t hpix, uint16_t vpix)
282 {
283 LCDx->MPUAR = (uint32_t)buff;
284
285 LCDx->MPULEN = ((vpix - 1) << LCD_MPULEN_VPIX_Pos) |
286 ((hpix - 1) << LCD_MPULEN_HPIX_Pos);
287
288 LCDx->START |= (1 << LCD_START_GO_Pos);
289 }
290
291 /******************************************************************************************************************************************
292 * 函数名称: MPULCD_DMABusy()
293 * 功能说明: MPU LCD DMA搬运显示数据忙查询
294 * 输 入: LCD_TypeDef * LCDx 指定要被设置的LCD,有效值包括LCD
295 * 输 出: uint32_t 1 搬运中 0 搬运完成
296 * 注意事项: 无
297 ******************************************************************************************************************************************/
MPULCD_DMABusy(LCD_TypeDef * LCDx)298 uint32_t MPULCD_DMABusy(LCD_TypeDef * LCDx)
299 {
300 return (LCDx->START & LCD_START_GO_Msk) ? 1 : 0;
301 }
302