1、 触摸屏驱动
触摸屏驱动的原理非常简单,从硬件得到坐标数据,数据加工(适配屏幕分辨率,偏移量调整),最后调用rtgui_server_post_event()函数向GUI服务端发送坐标信息。
奋斗板V3,使用的AD芯片是XPT2046,是RTGUI bsp/stm32f10x下的ADS7846芯片的下一代产品,功能及硬件连接上完全兼容。因此,我们只要确认与MCU的管脚连接,在代码上正确配置即可。
注:奋斗板的源代码是以模数转换(ADS)方式直接读取的,而RTGUI里,则是以SPI方式读取,并采用中断(EXT INT)方式。另外,SPI1上接了三个设备,分别是触摸屏,10M LAN, 2M Flash,使用了三根MCU管脚作为片选(CS)。RTT中,使用的CS脚是PC4,IRQ是PB1,而奋斗板的CS是PB7,IRQ是PB6。
驱动代码对比:
touch.c | touch.rtt.c | ||
1 | #include <stdbool.h> | 1 | #include <stdbool.h> |
2 | #include "stm32f10x.h" | 2 | #include "stm32f10x.h" |
3 |
| 3 |
|
4 | #include "board.h" | 4 | #include "board.h" |
5 | #include "touch.h" | 5 | #include "touch.h" |
6 |
| 6 |
|
7 | #include <rtthread.h> | 7 | #include <rtthread.h> |
8 | #include <rtgui/event.h> | 8 | #include <rtgui/event.h> |
9 | #include <rtgui/kbddef.h> | 9 | #include <rtgui/kbddef.h> |
10 | #include <rtgui/rtgui_server.h> | 10 | #include <rtgui/rtgui_server.h> |
11 | #include <rtgui/rtgui_system.h> | 11 | #include <rtgui/rtgui_system.h> |
12 |
| 12 |
|
13 | /* | 13 | /* |
14 | MISO PA6 | 14 | MISO PA6 |
15 | MOSI PA7 | 15 | MOSI PA7 |
16 | CLK PA5 | 16 | CLK PA5 |
17 | CS PB7 | 17 | CS PC4 |
18 | */ | 18 | */ |
19 |
| 19 |
|
20 | #define CS_0() GPIO_ResetBits(GPIOB,GPIO_Pin_7) | 20 | #define CS_0() GPIO_ResetBits(GPIOC,GPIO_Pin_4) |
21 | #define CS_1() GPIO_SetBits(GPIOB,GPIO_Pin_7) | 21 | #define CS_1() GPIO_SetBits(GPIOC,GPIO_Pin_4) |
22 |
| 22 |
|
23 | /* | 23 | /* |
24 | 7 6 - 4 3 2 1-0 | 24 | 7 6 - 4 3 2 1-0 |
25 | s A2-A0 MODE SER/DFR PD1-PD0 | 25 | s A2-A0 MODE SER/DFR PD1-PD0 |
26 | */ | 26 | */ |
27 | #define TOUCH_MSR_Y 0x90 //读X轴坐标指令 addr:1 | 27 | #define TOUCH_MSR_Y 0x90 //读X轴坐标指令 addr:1 |
28 | #define TOUCH_MSR_X 0xD0 //读Y轴坐标指令 addr:3 | 28 | #define TOUCH_MSR_X 0xD0 //读Y轴坐标指令 addr:3 |
29 |
| 29 |
|
30 | structrtgui_touch_device | 30 | structrtgui_touch_device |
31 | { | 31 | { |
32 | structrt_deviceparent; | 32 | structrt_deviceparent; |
33 |
| 33 |
|
34 | rt_timer_tpoll_timer; | 34 | rt_timer_tpoll_timer; |
35 | rt_uint16_tx, y; | 35 | rt_uint16_tx, y; |
36 |
| 36 |
|
37 | rt_bool_tcalibrating; | 37 | rt_bool_tcalibrating; |
38 | rt_touch_calibration_func_tcalibration_func; | 38 | rt_touch_calibration_func_tcalibration_func; |
39 |
| 39 |
|
40 | rt_uint16_tmin_x, max_x; | 40 | rt_uint16_tmin_x, max_x; |
41 | rt_uint16_tmin_y, max_y; | 41 | rt_uint16_tmin_y, max_y; |
42 | }; | 42 | }; |
43 | staticstructrtgui_touch_device *touch = RT_NULL; | 43 | staticstructrtgui_touch_device *touch = RT_NULL; |
44 |
| 44 |
|
45 | externunsignedcharSPI_WriteByte(unsignedchardata); | 45 | externunsignedcharSPI_WriteByte(unsignedchardata); |
46 | rt_inlinevoidEXTI_Enable(rt_uint32_tenable); | 46 | rt_inlinevoidEXTI_Enable(rt_uint32_tenable); |
47 |
| 47 |
|
48 | structrt_semaphorespi1_lock; | 48 | structrt_semaphorespi1_lock; |
49 |
| 49 |
|
50 | voidrt_hw_spi1_baud_rate(uint16_tSPI_BaudRatePrescaler) | 50 | voidrt_hw_spi1_baud_rate(uint16_tSPI_BaudRatePrescaler) |
51 | { | 51 | { |
52 | SPI1->CR1 &= ~SPI_BaudRatePrescaler_256; | 52 | SPI1->CR1 &= ~SPI_BaudRatePrescaler_256; |
53 | SPI1->CR1 |= SPI_BaudRatePrescaler; | 53 | SPI1->CR1 |= SPI_BaudRatePrescaler; |
54 | } | 54 | } |
55 |
| 55 |
|
56 | uint8_tSPI_WriteByte(unsignedchardata) | 56 | uint8_tSPI_WriteByte(unsignedchardata) |
57 | { | 57 | { |
58 | //Wait until the transmit buffer is empty | 58 | //Wait until the transmit buffer is empty |
59 | while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); | 59 | while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); |
60 | // Send the byte | 60 | // Send the byte |
61 | SPI_I2S_SendData(SPI1, data); | 61 | SPI_I2S_SendData(SPI1, data); |
62 |
| 62 |
|
63 | //Wait until a data is received | 63 | //Wait until a data is received |
64 | while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); | 64 | while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); |
65 | // Get the received data | 65 | // Get the received data |
66 | data = SPI_I2S_ReceiveData(SPI1); | 66 | data = SPI_I2S_ReceiveData(SPI1); |
67 |
| 67 |
|
68 | // Return the shifted data | 68 | // Return the shifted data |
69 | returndata; | 69 | returndata; |
70 | } | 70 | } |
71 |
| 71 |
|
72 | //SPI写数据 | 72 | //SPI写数据 |
73 | staticvoidWriteDataTo7843(unsignedcharnum) | 73 | staticvoidWriteDataTo7843(unsignedcharnum) |
74 | { | 74 | { |
75 | SPI_WriteByte(num); | 75 | SPI_WriteByte(num); |
76 | } | 76 | } |
77 |
| 77 |
|
78 | #define X_WIDTH 480 | 78 | #define X_WIDTH 240 |
79 | #define Y_WIDTH 272 | 79 | #define Y_WIDTH 320 |
80 |
| 80 |
|
81 | staticvoidrtgui_touch_calculate() | 81 | staticvoidrtgui_touch_calculate() |
82 | { | 82 | { |
83 | if (touch != RT_NULL) | 83 | if (touch != RT_NULL) |
84 | { | 84 | { |
85 | rt_sem_take(&spi1_lock, RT_WAITING_FOREVER); | 85 | rt_sem_take(&spi1_lock, RT_WAITING_FOREVER); |
86 | /* SPI1 configure */ | 86 | /* SPI1 configure */ |
87 | rt_hw_spi1_baud_rate(SPI_BaudRatePrescaler_64);/* 72M/64=1.125M */ | 87 | rt_hw_spi1_baud_rate(SPI_BaudRatePrescaler_64);/* 72M/64=1.125M */ |
88 |
| 88 |
|
89 | //读取触摸值 | 89 | //读取触摸值 |
90 | { | 90 | { |
91 | rt_uint16_ttmpx[10]; | 91 | rt_uint16_ttmpx[10]; |
92 | rt_uint16_ttmpy[10]; | 92 | rt_uint16_ttmpy[10]; |
93 | unsignedinti; | 93 | unsignedinti; |
94 |
| 94 |
|
95 | /* From the datasheet: | 95 | /* From the datasheet: |
96 | * When the very first CLK after the control byte comes in, the | 96 | * When the very first CLK after the control byte comes in, the |
97 | * DOUT of ADS7843 is not valid. So we could only get 7bits from | 97 | * DOUT of ADS7843 is not valid. So we could only get 7bits from |
98 | * the first SPI_WriteByte. And the got the following 5 bits from | 98 | * the first SPI_WriteByte. And the got the following 5 bits from |
99 | * another SPI_WriteByte.(aligned MSB) | 99 | * another SPI_WriteByte.(aligned MSB) |
100 | */ | 100 | */ |
101 | for(i=0; i<10; i++) | 101 | for(i=0; i<10; i++) |
102 | { | 102 | { |
103 | CS_0(); | 103 | CS_0(); |
104 | WriteDataTo7843(TOUCH_MSR_X); | 104 | WriteDataTo7843(TOUCH_MSR_X); |
105 | tmpx[i] = (SPI_WriteByte(0x00) & 0x7F) << 5; | 105 | tmpx[i] = (SPI_WriteByte(0x00) & 0x7F) << 5; |
106 | tmpx[i] |= (SPI_WriteByte(TOUCH_MSR_Y) >> 3) & 0x1F; | 106 | tmpx[i] |= (SPI_WriteByte(TOUCH_MSR_Y) >> 3) & 0x1F; |
107 |
| 107 |
|
108 | tmpy[i] = (SPI_WriteByte(0x00) & 0x7F) << 5; | 108 | tmpy[i] = (SPI_WriteByte(0x00) & 0x7F) << 5; |
109 | tmpy[i] |= (SPI_WriteByte(0x00) >> 3) & 0x1F; | 109 | tmpy[i] |= (SPI_WriteByte(0x00) >> 3) & 0x1F; |
110 |
| 110 |
|
111 | WriteDataTo7843( 1<<7 ); /* 打开中断 */ | 111 | WriteDataTo7843( 1<<7 ); /* 打开中断 */ |
112 | CS_1(); | 112 | CS_1(); |
113 | } | 113 | } |
114 |
| 114 |
|
115 | //去最高值与最低值,再取平均值 | 115 | //去最高值与最低值,再取平均值 |
116 | { | 116 | { |
117 | rt_uint32_tmin_x = 0xFFFF,min_y = 0xFFFF; | 117 | rt_uint32_tmin_x = 0xFFFF,min_y = 0xFFFF; |
118 | rt_uint32_tmax_x = 0,max_y = 0; | 118 | rt_uint32_tmax_x = 0,max_y = 0; |
119 | rt_uint32_ttotal_x = 0; | 119 | rt_uint32_ttotal_x = 0; |
120 | rt_uint32_ttotal_y = 0; | 120 | rt_uint32_ttotal_y = 0; |
121 | unsignedinti; | 121 | unsignedinti; |
122 |
| 122 |
|
123 | for(i=0;i<10;i++) | 123 | for(i=0;i<10;i++) |
124 | { | 124 | { |
125 | if( tmpx[i] < min_x ) | 125 | if( tmpx[i] < min_x ) |
126 | { | 126 | { |
127 | min_x = tmpx[i]; | 127 | min_x = tmpx[i]; |
128 | } | 128 | } |
129 | if( tmpx[i] > max_x ) | 129 | if( tmpx[i] > max_x ) |
130 | { | 130 | { |
131 | max_x = tmpx[i]; | 131 | max_x = tmpx[i]; |
132 | } | 132 | } |
133 | total_x += tmpx[i]; | 133 | total_x += tmpx[i]; |
134 |
| 134 |
|
135 | if( tmpy[i] < min_y ) | 135 | if( tmpy[i] < min_y ) |
136 | { | 136 | { |
137 | min_y = tmpy[i]; | 137 | min_y = tmpy[i]; |
138 | } | 138 | } |
139 | if( tmpy[i] > max_y ) | 139 | if( tmpy[i] > max_y ) |
140 | { | 140 | { |
141 | max_y = tmpy[i]; | 141 | max_y = tmpy[i]; |
142 | } | 142 | } |
143 | total_y += tmpy[i]; | 143 | total_y += tmpy[i]; |
144 | } | 144 | } |
145 | total_x = total_x - min_x - max_x; | 145 | total_x = total_x - min_x - max_x; |
146 | total_y = total_y - min_y - max_y; | 146 | total_y = total_y - min_y - max_y; |
147 | touch->y = total_x / 8; | 147 | touch->x = total_x / 8; |
148 | touch->x = total_y / 8; | 148 | touch->y = total_y / 8; |
149 | }//去最高值与最低值,再取平均值 | 149 | }//去最高值与最低值,再取平均值 |
150 | }//读取触摸值 | 150 | }//读取触摸值 |
151 |
| 151 |
|
152 | rt_sem_release(&spi1_lock); | 152 | rt_sem_release(&spi1_lock); |
153 |
| 153 |
|
154 | rt_kprintf("physical position: (%d, %d)\n", touch->x, touch->y); |
| |
155 |
|
| |
156 | /* if it's not in calibration status */ | 154 | /* if it's not in calibration status */ |
157 | if (touch->calibrating != RT_TRUE) | 155 | if (touch->calibrating != RT_TRUE) |
158 | { | 156 | { |
159 | if (touch->max_x > touch->min_x) | 157 | if (touch->max_x > touch->min_x) |
160 | { | 158 | { |
161 | touch->x = (touch->x - touch->min_x) * X_WIDTH/(touch->max_x - touch->min_x); | 159 | touch->x = (touch->x - touch->min_x) * X_WIDTH/(touch->max_x - touch->min_x); |
162 | } | 160 | } |
163 | elseif (touch->max_x < touch->min_x) | 161 | elseif (touch->max_x < touch->min_x) |
164 | { | 162 | { |
165 | touch->x = (touch->min_x - touch->x) * X_WIDTH/(touch->min_x - touch->max_x); | 163 | touch->x = (touch->min_x - touch->x) * X_WIDTH/(touch->min_x - touch->max_x); |
166 | } | 164 | } |
167 |
| 165 |
|
168 | if (touch->max_y > touch->min_y) | 166 | if (touch->max_y > touch->min_y) |
169 | { | 167 | { |
170 | touch->y = (touch->y - touch->min_y) * Y_WIDTH /(touch->max_y - touch->min_y); | 168 | touch->y = (touch->y - touch->min_y) * Y_WIDTH /(touch->max_y - touch->min_y); |
171 | } | 169 | } |
172 | elseif (touch->max_y < touch->min_y) | 170 | elseif (touch->max_y < touch->min_y) |
173 | { | 171 | { |
174 | touch->y = (touch->min_y - touch->y) * Y_WIDTH /(touch->min_y - touch->max_y); | 172 | touch->y = (touch->min_y - touch->y) * Y_WIDTH /(touch->min_y - touch->max_y); |
175 | } | 173 | } |
176 |
| 174 |
|
177 | // normalize the data | 175 | // normalize the data |
178 | if (touch->x & 0x8000) | 176 | if (touch->x & 0x8000) |
179 | touch->x = 0; | 177 | touch->x = 0; |
180 | elseif (touch->x > X_WIDTH) | 178 | elseif (touch->x > X_WIDTH) |
181 | touch->x = X_WIDTH - 1; | 179 | touch->x = X_WIDTH - 1; |
182 |
| 180 |
|
183 | if (touch->y & 0x8000) | 181 | if (touch->y & 0x8000) |
184 | touch->y = 0; | 182 | touch->y = 0; |
185 | elseif (touch->y > Y_WIDTH) | 183 | elseif (touch->y > Y_WIDTH) |
186 | touch->y = Y_WIDTH - 1; | 184 | touch->y = Y_WIDTH - 1; |
187 | } | 185 | } |
188 | } | 186 | } |
189 | } | 187 | } |
190 |
| 188 |
|
191 | voidtouch_timeout(void* parameter) | 189 | voidtouch_timeout(void* parameter) |
192 | { | 190 | { |
193 | staticunsignedinttouched_down = 0; | 191 | staticunsignedinttouched_down = 0; |
194 | structrtgui_event_mouseemouse; | 192 | structrtgui_event_mouseemouse; |
195 | staticstruct_touch_previous | 193 | staticstruct_touch_previous |
196 | { | 194 | { |
197 | rt_uint32_tx; | 195 | rt_uint32_tx; |
198 | rt_uint32_ty; | 196 | rt_uint32_ty; |
199 | } touch_previous; | 197 | } touch_previous; |
200 |
| 198 |
|
201 | /* touch time is too short and we lost the position already. */ | 199 | /* touch time is too short and we lost the position already. */ |
202 | if ((!touched_down) && GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_6) != 0) | 200 | if ((!touched_down) && GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) != 0) |
203 | return; | 201 | return; |
204 |
| 202 |
|
205 | if (GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6) != 0) | 203 | if (GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) != 0) |
206 | { | 204 | { |
207 | inttmer = RT_TICK_PER_SECOND/8 ; | 205 | inttmer = RT_TICK_PER_SECOND/8 ; |
208 | EXTI_Enable(1); | 206 | EXTI_Enable(1); |
209 | emouse.parent.type = RTGUI_EVENT_MOUSE_BUTTON; | 207 | emouse.parent.type = RTGUI_EVENT_MOUSE_BUTTON; |
210 | emouse.button = (RTGUI_MOUSE_BUTTON_LEFT |RTGUI_MOUSE_BUTTON_UP); | 208 | emouse.button = (RTGUI_MOUSE_BUTTON_LEFT |RTGUI_MOUSE_BUTTON_UP); |
211 |
| 209 |
|
212 | /* use old value */ | 210 | /* use old value */ |
213 | emouse.x = touch->x; | 211 | emouse.x = touch->x; |
214 | emouse.y = touch->y; | 212 | emouse.y = touch->y; |
215 |
| 213 |
|
216 | /* stop timer */ | 214 | /* stop timer */ |
217 | rt_timer_stop(touch->poll_timer); | 215 | rt_timer_stop(touch->poll_timer); |
218 | rt_kprintf("touch up: (%d, %d)\n", emouse.x, emouse.y); | 216 | rt_kprintf("touch up: (%d, %d)\n", emouse.x, emouse.y); |
219 | touched_down = 0; | 217 | touched_down = 0; |
220 |
| 218 |
|
221 | if ((touch->calibrating == RT_TRUE) && (touch->calibration_func != RT_NULL)) | 219 | if ((touch->calibrating == RT_TRUE) && (touch->calibration_func != RT_NULL)) |
222 | { | 220 | { |
223 | /* callback function */ | 221 | /* callback function */ |
224 | touch->calibration_func(emouse.x, emouse.y); | 222 | touch->calibration_func(emouse.x, emouse.y); |
225 | } | 223 | } |
226 | rt_timer_control(touch->poll_timer , RT_TIMER_CTRL_SET_TIME , &tmer); | 224 | rt_timer_control(touch->poll_timer , RT_TIMER_CTRL_SET_TIME , &tmer); |
227 | } | 225 | } |
228 | else | 226 | else |
229 | { | 227 | { |
230 | if(touched_down == 0) | 228 | if(touched_down == 0) |
231 | { | 229 | { |
232 | inttmer = RT_TICK_PER_SECOND/20 ; | 230 | inttmer = RT_TICK_PER_SECOND/20 ; |
233 | /* calculation */ | 231 | /* calculation */ |
234 | rtgui_touch_calculate(); | 232 | rtgui_touch_calculate(); |
235 |
| 233 |
|
236 | /* send mouse event */ | 234 | /* send mouse event */ |
237 | emouse.parent.type = RTGUI_EVENT_MOUSE_BUTTON; | 235 | emouse.parent.type = RTGUI_EVENT_MOUSE_BUTTON; |
238 | emouse.parent.sender = RT_NULL; | 236 | emouse.parent.sender = RT_NULL; |
239 |
| 237 |
|
240 | emouse.x = touch->x; | 238 | emouse.x = touch->x; |
241 | emouse.y = touch->y; | 239 | emouse.y = touch->y; |
242 |
| 240 |
|
243 | touch_previous.x = touch->x; | 241 | touch_previous.x = touch->x; |
244 | touch_previous.y = touch->y; | 242 | touch_previous.y = touch->y; |
245 |
| 243 |
|
246 | /* init mouse button */ | 244 | /* init mouse button */ |
247 | emouse.button = (RTGUI_MOUSE_BUTTON_LEFT |RTGUI_MOUSE_BUTTON_DOWN); | 245 | emouse.button = (RTGUI_MOUSE_BUTTON_LEFT |RTGUI_MOUSE_BUTTON_DOWN); |
248 |
| 246 |
|
249 | // rt_kprintf("touch down: (%d, %d)\n", emouse.x, emouse.y); | 247 | // rt_kprintf("touch down: (%d, %d)\n", emouse.x, emouse.y); |
250 | touched_down = 1; | 248 | touched_down = 1; |
251 | rt_timer_control(touch->poll_timer , RT_TIMER_CTRL_SET_TIME , &tmer); | 249 | rt_timer_control(touch->poll_timer , RT_TIMER_CTRL_SET_TIME , &tmer); |
252 | } | 250 | } |
253 | else | 251 | else |
254 | { | 252 | { |
255 | /* calculation */ | 253 | /* calculation */ |
256 | rtgui_touch_calculate(); | 254 | rtgui_touch_calculate(); |
257 |
| 255 |
|
258 | #define previous_keep 8 | 256 | #define previous_keep 8 |
259 | //判断移动距离是否小于previous_keep,减少误动作. | 257 | //判断移动距离是否小于previous_keep,减少误动作. |
260 | if( | 258 | if( |
261 | (touch_previous.x<touch->x+previous_keep) | 259 | (touch_previous.x<touch->x+previous_keep) |
262 | && (touch_previous.x>touch->x-previous_keep) | 260 | && (touch_previous.x>touch->x-previous_keep) |
263 | && (touch_previous.y<touch->y+previous_keep) | 261 | && (touch_previous.y<touch->y+previous_keep) |
264 | && (touch_previous.y>touch->y-previous_keep) ) | 262 | && (touch_previous.y>touch->y-previous_keep) ) |
265 | { | 263 | { |
266 | return; | 264 | return; |
267 | } | 265 | } |
268 |
| 266 |
|
269 | touch_previous.x = touch->x; | 267 | touch_previous.x = touch->x; |
270 | touch_previous.y = touch->y; | 268 | touch_previous.y = touch->y; |
271 |
| 269 |
|
272 | /* send mouse event */ | 270 | /* send mouse event */ |
273 | emouse.parent.type = RTGUI_EVENT_MOUSE_BUTTON ; | 271 | emouse.parent.type = RTGUI_EVENT_MOUSE_BUTTON ; |
274 | emouse.parent.sender = RT_NULL; | 272 | emouse.parent.sender = RT_NULL; |
275 |
| 273 |
|
276 | emouse.x = touch->x; | 274 | emouse.x = touch->x; |
277 | emouse.y = touch->y; | 275 | emouse.y = touch->y; |
278 |
| 276 |
|
279 | /* init mouse button */ | 277 | /* init mouse button */ |
280 | emouse.button = (RTGUI_MOUSE_BUTTON_RIGHT |RTGUI_MOUSE_BUTTON_DOWN); | 278 | emouse.button = (RTGUI_MOUSE_BUTTON_RIGHT |RTGUI_MOUSE_BUTTON_DOWN); |
281 | // rt_kprintf("touch motion: (%d, %d)\n", emouse.x, emouse.y); | 279 | // rt_kprintf("touch motion: (%d, %d)\n", emouse.x, emouse.y); |
282 | } | 280 | } |
283 | } | 281 | } |
284 |
| 282 |
|
285 | /* send event to server */ | 283 | /* send event to server */ |
286 | if (touch->calibrating != RT_TRUE) | 284 | if (touch->calibrating != RT_TRUE) |
287 | rtgui_server_post_event(&emouse.parent, sizeof(structrtgui_event_mouse)); | 285 | rtgui_server_post_event(&emouse.parent, sizeof(structrtgui_event_mouse)); |
288 | } | 286 | } |
289 |
| 287 |
|
290 | staticvoidNVIC_Configuration(void) | 288 | staticvoidNVIC_Configuration(void) |
291 | { | 289 | { |
292 | NVIC_InitTypeDefNVIC_InitStructure; | 290 | NVIC_InitTypeDefNVIC_InitStructure; |
293 |
| 291 |
|
294 | /* Enable the EXTI9_5 Interrupt */ | 292 | /* Enable the EXTI0 Interrupt */ |
295 | NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; | 293 | NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn; |
296 | NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; | 294 | NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; |
297 | NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; | 295 | NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; |
298 | NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; | 296 | NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; |
299 | NVIC_Init(&NVIC_InitStructure); | 297 | NVIC_Init(&NVIC_InitStructure); |
300 | } | 298 | } |
301 |
| 299 |
|
302 | rt_inlinevoidEXTI_Enable(rt_uint32_tenable) | 300 | rt_inlinevoidEXTI_Enable(rt_uint32_tenable) |
303 | { | 301 | { |
304 | EXTI_InitTypeDefEXTI_InitStructure; | 302 | EXTI_InitTypeDefEXTI_InitStructure; |
305 |
| 303 |
|
306 | /* Configure EXTI */ | 304 | /* Configure EXTI */ |
307 | EXTI_InitStructure.EXTI_Line = EXTI_Line6; | 305 | EXTI_InitStructure.EXTI_Line = EXTI_Line1; |
308 | EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; | 306 | EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; |
309 | EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//Falling下降沿 Rising上升 | 307 | EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//Falling下降沿 Rising上升 |
310 |
| 308 |
|
311 | if (enable) | 309 | if (enable) |
312 | { | 310 | { |
313 | /* enable */ | 311 | /* enable */ |
314 | EXTI_InitStructure.EXTI_LineCmd = ENABLE; | 312 | EXTI_InitStructure.EXTI_LineCmd = ENABLE; |
315 | } | 313 | } |
316 | else | 314 | else |
317 | { | 315 | { |
318 | /* disable */ | 316 | /* disable */ |
319 | EXTI_InitStructure.EXTI_LineCmd = DISABLE; | 317 | EXTI_InitStructure.EXTI_LineCmd = DISABLE; |
320 | } | 318 | } |
321 |
| 319 |
|
322 | EXTI_Init(&EXTI_InitStructure); | 320 | EXTI_Init(&EXTI_InitStructure); |
323 | EXTI_ClearITPendingBit(EXTI_Line6); | 321 | EXTI_ClearITPendingBit(EXTI_Line1); |
324 | } | 322 | } |
325 |
| 323 |
|
326 | staticvoidEXTI_Configuration(void) | 324 | staticvoidEXTI_Configuration(void) |
327 | { | 325 | { |
328 | /* PB6 touch INT */ | 326 | /* PB1 touch INT */ |
329 | { | 327 | { |
330 | GPIO_InitTypeDefGPIO_InitStructure; | 328 | GPIO_InitTypeDefGPIO_InitStructure; |
331 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); | 329 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); |
332 |
| 330 |
|
333 | GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; | 331 | GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; |
334 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; | 332 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; |
335 | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; | 333 | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; |
336 | GPIO_Init(GPIOB,&GPIO_InitStructure); | 334 | GPIO_Init(GPIOB,&GPIO_InitStructure); |
337 | } | 335 | } |
338 |
| 336 |
|
339 | GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource6); | 337 | GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource1); |
340 |
| 338 |
|
341 | /* Configure EXTI */ | 339 | /* Configure EXTI */ |
342 | EXTI_Enable(1); | 340 | EXTI_Enable(1); |
343 | } | 341 | } |
344 |
| 342 |
|
345 | /* RT-Thread Device Interface */ | 343 | /* RT-Thread Device Interface */ |
346 | staticrt_err_trtgui_touch_init (rt_device_tdev) | 344 | staticrt_err_trtgui_touch_init (rt_device_tdev) |
347 | { | 345 | { |
348 | NVIC_Configuration(); | 346 | NVIC_Configuration(); |
349 | EXTI_Configuration(); | 347 | EXTI_Configuration(); |
350 |
| 348 |
|
351 | // enable touch, disable other SPI1 device | 349 | /* PC4 touch CS */ |
352 | { | 350 | { |
353 | GPIO_InitTypeDefGPIO_InitStructure; | 351 | GPIO_InitTypeDefGPIO_InitStructure; |
354 |
| 352 |
|
355 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOB, ENABLE); | 353 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); |
356 |
| 354 |
|
357 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; | 355 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; |
358 | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; | 356 | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; |
359 | GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; | 357 | GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; |
360 | GPIO_Init(GPIOA,&GPIO_InitStructure); |
| |
361 | GPIO_Init(GPIOC,&GPIO_InitStructure); | 358 | GPIO_Init(GPIOC,&GPIO_InitStructure); |
362 |
| 359 | CS_1(); |
363 | GPIO_SetBits(GPIOA, GPIO_Pin_4); // disable ENC28J60(LAN) |
| |
364 | GPIO_SetBits(GPIOB, GPIO_Pin_4); // disable SST25VF016B(2M Flash) |
| |
365 |
|
| |
366 | /* PB7 touch CS */ |
| |
367 | { |
| |
368 | GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; |
| |
369 | GPIO_Init(GPIOB,&GPIO_InitStructure); |
| |
370 | CS_1(); |
| |
371 | } |
| |
372 | } | 360 | } |
373 |
| 361 |
|
374 | CS_0(); | 362 | CS_0(); |
375 | WriteDataTo7843( 1<<7 ); /* 打开中断 */ | 363 | WriteDataTo7843( 1<<7 ); /* 打开中断 */ |
376 | CS_1(); | 364 | CS_1(); |
377 |
| 365 |
|
378 | returnRT_EOK; | 366 | returnRT_EOK; |
379 | } | 367 | } |
380 |
| 368 |
|
381 | staticrt_err_trtgui_touch_control (rt_device_tdev, rt_uint8_tcmd, void *args) | 369 | staticrt_err_trtgui_touch_control (rt_device_tdev, rt_uint8_tcmd, void *args) |
382 | { | 370 | { |
383 | switch (cmd) | 371 | switch (cmd) |
384 | { | 372 | { |
385 | caseRT_TOUCH_CALIBRATION: | 373 | caseRT_TOUCH_CALIBRATION: |
386 | touch->calibrating = RT_TRUE; | 374 | touch->calibrating = RT_TRUE; |
387 | touch->calibration_func = (rt_touch_calibration_func_t)args; | 375 | touch->calibration_func = (rt_touch_calibration_func_t)args; |
388 | break; | 376 | break; |
389 |
| 377 |
|
390 | caseRT_TOUCH_NORMAL: | 378 | caseRT_TOUCH_NORMAL: |
391 | touch->calibrating = RT_FALSE; | 379 | touch->calibrating = RT_FALSE; |
392 | break; | 380 | break; |
393 |
| 381 |
|
394 | caseRT_TOUCH_CALIBRATION_DATA: | 382 | caseRT_TOUCH_CALIBRATION_DATA: |
395 | { | 383 | { |
396 | structcalibration_data* data; | 384 | structcalibration_data* data; |
397 |
| 385 |
|
398 | data = (structcalibration_data*) args; | 386 | data = (structcalibration_data*) args; |
399 |
| 387 |
|
400 | //update | 388 | //update |
401 | touch->min_x = data->min_x; | 389 | touch->min_x = data->min_x; |
402 | touch->max_x = data->max_x; | 390 | touch->max_x = data->max_x; |
403 | touch->min_y = data->min_y; | 391 | touch->min_y = data->min_y; |
404 | touch->max_y = data->max_y; | 392 | touch->max_y = data->max_y; |
405 | } | 393 | } |
406 | break; | 394 | break; |
407 | } | 395 | } |
408 |
| 396 |
|
409 | returnRT_EOK; | 397 | returnRT_EOK; |
410 | } | 398 | } |
411 |
| 399 |
|
412 | void EXTI9_5_IRQHandler(void) | 400 | void EXTI1_IRQHandler(void) |
413 | { | 401 | { |
414 | /* disable interrupt */ | 402 | /* disable interrupt */ |
415 | EXTI_Enable(0); | 403 | EXTI_Enable(0); |
416 |
| 404 |
|
417 | /* start timer */ | 405 | /* start timer */ |
418 | rt_timer_start(touch->poll_timer); | 406 | rt_timer_start(touch->poll_timer); |
419 |
| 407 |
|
420 | EXTI_ClearITPendingBit(EXTI_Line6); | 408 | EXTI_ClearITPendingBit(EXTI_Line1); |
421 | } | 409 | } |
422 |
| 410 |
|
423 | voidrtgui_touch_hw_init(void) | 411 | voidrtgui_touch_hw_init(void) |
424 | { | 412 | { |
425 | /* SPI1 config */ | 413 | /* SPI1 config */ |
426 | { | 414 | { |
427 | GPIO_InitTypeDefGPIO_InitStructure; | 415 | GPIO_InitTypeDefGPIO_InitStructure; |
428 | SPI_InitTypeDefSPI_InitStructure; | 416 | SPI_InitTypeDefSPI_InitStructure; |
429 |
| 417 |
|
430 | /* Enable SPI1 Periph clock */ | 418 | /* Enable SPI1 Periph clock */ |
431 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | 419 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |
432 | | RCC_APB2Periph_AFIO | RCC_APB2Periph_SPI1, | 420 | | RCC_APB2Periph_AFIO | RCC_APB2Periph_SPI1, |
433 | ENABLE); | 421 | ENABLE); |
434 |
| 422 |
|
435 | /* Configure SPI1 pins: PA5-SCK, PA6-MISO and PA7-MOSI */ | 423 | /* Configure SPI1 pins: PA5-SCK, PA6-MISO and PA7-MOSI */ |
436 | GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; | 424 | GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; |
437 | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; | 425 | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; |
438 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; | 426 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; |
439 | GPIO_Init(GPIOA, &GPIO_InitStructure); | 427 | GPIO_Init(GPIOA, &GPIO_InitStructure); |
440 |
| 428 |
|
441 | /*------------------------ SPI1 configuration ------------------------*/ | 429 | /*------------------------ SPI1 configuration ------------------------*/ |
442 | SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//SPI_Direction_1Line_Tx; | 430 | SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//SPI_Direction_1Line_Tx; |
443 | SPI_InitStructure.SPI_Mode = SPI_Mode_Master; | 431 | SPI_InitStructure.SPI_Mode = SPI_Mode_Master; |
444 | SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; | 432 | SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; |
445 | SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; | 433 | SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; |
446 | SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; | 434 | SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; |
447 | SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; | 435 | SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; |
448 | SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64;/* 72M/64=1.125M */ | 436 | SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64;/* 72M/64=1.125M */ |
449 | SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; | 437 | SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; |
450 | SPI_InitStructure.SPI_CRCPolynomial = 7; | 438 | SPI_InitStructure.SPI_CRCPolynomial = 7; |
451 |
| 439 |
|
452 | SPI_I2S_DeInit(SPI1); | 440 | SPI_I2S_DeInit(SPI1); |
453 | SPI_Init(SPI1, &SPI_InitStructure); | 441 | SPI_Init(SPI1, &SPI_InitStructure); |
454 |
| 442 |
|
455 | /* Enable SPI_MASTER */ | 443 | /* Enable SPI_MASTER */ |
456 | SPI_Cmd(SPI1, ENABLE); | 444 | SPI_Cmd(SPI1, ENABLE); |
457 | SPI_CalculateCRC(SPI1, DISABLE); | 445 | SPI_CalculateCRC(SPI1, DISABLE); |
458 |
| 446 |
|
459 | if (rt_sem_init(&spi1_lock, "spi1lock", 1, RT_IPC_FLAG_FIFO) != RT_EOK) | 447 | if (rt_sem_init(&spi1_lock, "spi1lock", 1, RT_IPC_FLAG_FIFO) != RT_EOK) |
460 | { | 448 | { |
461 | rt_kprintf("init spi1 lock semaphore failed\n"); | 449 | rt_kprintf("init spi1 lock semaphore failed\n"); |
462 | } | 450 | } |
463 | } /* SPI1 config */ | 451 | } /* SPI1 config */ |
464 |
| 452 |
|
465 | touch = (structrtgui_touch_device*)rt_malloc (sizeof(structrtgui_touch_device)); | 453 | touch = (structrtgui_touch_device*)rt_malloc (sizeof(structrtgui_touch_device)); |
466 | if (touch == RT_NULL) return; /* no memory yet */ | 454 | if (touch == RT_NULL) return; /* no memory yet */ |
467 |
| 455 |
|
468 | /* clear device structure */ | 456 | /* clear device structure */ |
469 | rt_memset(&(touch->parent), 0, sizeof(structrt_device)); | 457 | rt_memset(&(touch->parent), 0, sizeof(structrt_device)); |
470 | touch->calibrating = false; | 458 | touch->calibrating = false; |
471 |
| 459 |
|
472 | /* init device structure */ | 460 | /* init device structure */ |
473 | touch->parent.type = RT_Device_Class_Unknown; | 461 | touch->parent.type = RT_Device_Class_Unknown; |
474 | touch->parent.init = rtgui_touch_init; | 462 | touch->parent.init = rtgui_touch_init; |
475 | touch->parent.control = rtgui_touch_control; | 463 | touch->parent.control = rtgui_touch_control; |
476 | touch->parent.user_data = RT_NULL; | 464 | touch->parent.user_data = RT_NULL; |
477 |
| 465 |
|
478 | /* create 1/8 second timer */ | 466 | /* create 1/8 second timer */ |
479 | touch->poll_timer = rt_timer_create("touch", touch_timeout, RT_NULL, | 467 | touch->poll_timer = rt_timer_create("touch", touch_timeout, RT_NULL, |
480 | RT_TICK_PER_SECOND/8, RT_TIMER_FLAG_PERIODIC); | 468 | RT_TICK_PER_SECOND/8, RT_TIMER_FLAG_PERIODIC); |
481 |
| 469 |
|
482 | /* register touch device to RT-Thread */ | 470 | /* register touch device to RT-Thread */ |
483 | rt_device_register(&(touch->parent), "touch", RT_DEVICE_FLAG_RDWR); | 471 | rt_device_register(&(touch->parent), "touch", RT_DEVICE_FLAG_RDWR); |
484 | } | 472 | } |
485 |
| 473 |
|
486 | #ifdef RT_USING_FINSH | 474 | #ifdef RT_USING_FINSH |
487 | #include <finsh.h> | 475 | #include <finsh.h> |
488 |
| 476 |
|
489 | voidtouch_t( rt_uint16_tx , rt_uint16_ty ) | 477 | voidtouch_t( rt_uint16_tx , rt_uint16_ty ) |
490 | { | 478 | { |
491 | structrtgui_event_mouseemouse ; | 479 | structrtgui_event_mouseemouse ; |
492 | emouse.parent.type = RTGUI_EVENT_MOUSE_BUTTON; | 480 | emouse.parent.type = RTGUI_EVENT_MOUSE_BUTTON; |
493 | emouse.parent.sender = RT_NULL; | 481 | emouse.parent.sender = RT_NULL; |
494 |
| 482 |
|
495 | emouse.x = x ; | 483 | emouse.x = x ; |
496 | emouse.y = y ; | 484 | emouse.y = y ; |
497 | /* init mouse button */ | 485 | /* init mouse button */ |
498 | emouse.button = (RTGUI_MOUSE_BUTTON_LEFT |RTGUI_MOUSE_BUTTON_DOWN ); | 486 | emouse.button = (RTGUI_MOUSE_BUTTON_LEFT |RTGUI_MOUSE_BUTTON_DOWN ); |
499 | rtgui_server_post_event(&emouse.parent, sizeof(structrtgui_event_mouse)); | 487 | rtgui_server_post_event(&emouse.parent, sizeof(structrtgui_event_mouse)); |
500 |
| 488 |
|
501 | rt_thread_delay(2) ; | 489 | rt_thread_delay(2) ; |
502 | emouse.button = (RTGUI_MOUSE_BUTTON_LEFT |RTGUI_MOUSE_BUTTON_UP ); | 490 | emouse.button = (RTGUI_MOUSE_BUTTON_LEFT |RTGUI_MOUSE_BUTTON_UP ); |
503 | rtgui_server_post_event(&emouse.parent, sizeof(structrtgui_event_mouse)); | 491 | rtgui_server_post_event(&emouse.parent, sizeof(structrtgui_event_mouse)); |
504 | } | 492 | } |
505 |
| 493 |
|
506 | FINSH_FUNCTION_EXPORT(touch_t, x & y ) ; | 494 | FINSH_FUNCTION_EXPORT(touch_t, x & y ) ; |
507 | #endif | 495 | #endif |
508 |
| 496 |
|
补丁:
17c17 < CS PB7 --- > CS PC4 20,21c20,21 < #define CS_0() GPIO_ResetBits(GPIOB,GPIO_Pin_7) < #define CS_1() GPIO_SetBits(GPIOB,GPIO_Pin_7) --- > #define CS_0() GPIO_ResetBits(GPIOC,GPIO_Pin_4) > #define CS_1() GPIO_SetBits(GPIOC,GPIO_Pin_4) 78,79c78,79 < #define X_WIDTH 480 < #define Y_WIDTH 272 --- > #define X_WIDTH 240 > #define Y_WIDTH 320 147,148c147,148 < touch->y = total_x / 8; < touch->x = total_y / 8; --- > touch->x = total_x / 8; > touch->y = total_y / 8; 154,155d153 < rt_kprintf("physical position: (%d, %d)\n", touch->x, touch->y); < 202c200 < if ((!touched_down) && GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_6) != 0) --- > if ((!touched_down) && GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) != 0) 205c203 < if (GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6) != 0) --- > if (GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) != 0) 294,295c292,293 < /* Enable the EXTI9_5 Interrupt */ < NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; --- > /* Enable the EXTI0 Interrupt */ > NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn; 307c305 < EXTI_InitStructure.EXTI_Line = EXTI_Line6; --- > EXTI_InitStructure.EXTI_Line = EXTI_Line1; 323c321 < EXTI_ClearITPendingBit(EXTI_Line6); --- > EXTI_ClearITPendingBit(EXTI_Line1); 328c326 < /* PB6 touch INT */ --- > /* PB1 touch INT */ 333c331 < GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; --- > GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; 339c337 < GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource6); --- > GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource1); 351c349 < // enable touch, disable other SPI1 device --- > /* PC4 touch CS */ 355c353 < RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOB, ENABLE); --- > RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); 360d357 < GPIO_Init(GPIOA,&GPIO_InitStructure); 362,369d358 < < GPIO_SetBits(GPIOA, GPIO_Pin_4); // disable ENC28J60(LAN) < GPIO_SetBits(GPIOB, GPIO_Pin_4); // disable SST25VF016B(2M Flash) < < /* PB7 touch CS */ < { < GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; < GPIO_Init(GPIOB,&GPIO_InitStructure); 372d360 < } 412c400 < void EXTI9_5_IRQHandler(void) --- > void EXTI1_IRQHandler(void) 420c408 < EXTI_ClearITPendingBit(EXTI_Line6); --- > EXTI_ClearITPendingBit(EXTI_Line1); |
在 touch.c 中,第30行定义了一个结构体,其中最后两行,对于每个触摸屏,不同时期,可能采用不同的值才会取得最佳效果,这就是触摸屏校准程序要采集并计算的最佳数据。
struct rtgui_touch_device { struct rt_device parent;
rt_timer_t poll_timer; rt_uint16_t x, y;
rt_bool_t calibrating; rt_touch_calibration_func_t calibration_func;
rt_uint16_t min_x, max_x; rt_uint16_t min_y, max_y; };
|
数值例:
点触摸屏右下角,硬件返回的坐标值:3955, 3463
校准数据:min_x = 208, max_x = 4069, min_y = 187, max_y = 3590
最后,综合硬件值,校准数据,屏幕分辨率,计算出一个相对精确的坐标数据(x, y),如果屏幕分辨率为480 X 640,则x < 480,y < 640。
注1:由于屏幕显示方向与触摸屏方向不一致,在代码的第147行,将 x, y 值对调。
注2:为了屏幕与触摸屏方向保持一致,修改了LCD驱动,将显示方向转了180度。
Ssd1963.c 第188行,参数值改为0x0003
LCD_WR_REG(0x0036); //rotation LCD_WR_DAT(0x0003); |
具体参数意义,请参考PDF文件说明。