MCU stm32f103 fsmc
rt-thread: v2.01
rt-gui: v0.8
屏幕大小:800 * 480,横屏
扫描方式:中断
个人作简单测试,仅供参考。
delay.c
[mw_shl_code=c,true]#include "stm32f10x.h"
#include <rtthread.h>
#include "delay.h"
/**
* delay in us count, us must be less then 1 os tick.
* Reference: http://www.rt-thread.org/phpBB3/viewtopic.php?p=14266
*
* @param us the delay time in us
*/
void rt_hw_us_delay(int us)
{
rt_uint32_t delta;
rt_uint32_t current_delay;
/* 获得延时经过的tick数 */
us = us * (SysTick->LOAD/(1000000/RT_TICK_PER_SECOND));
/* 获得当前时间 */
delta = SysTick->VAL;
/* 循环获得当前时间,直到达到指定的时间后退出循环 */
do
{
if ( delta > SysTick->VAL )
current_delay = delta - SysTick->VAL;
else
/* 延时跨越了一次OS tick的边界时的处理 */
current_delay = SysTick->LOAD + delta - SysTick->VAL;
} while( current_delay < us );
}
/**
* ms should be great than one tick(10ms)
*/
void rt_thread_delay_ms(int ms)
{
rt_thread_delay(ms*RT_TICK_PER_SECOND/1000);
}[/mw_shl_code]
ctouch.c
[mw_shl_code=c,true]/*
* NOTE: OTT2001A buffer address is 16 bits, not 8 bits
*/
#include <stdbool.h>
#include "stm32f10x.h"
#include "board.h"
#include "ctouch.h"
#include "delay.h"
#include <rtthread.h>
#include <rtgui/event.h>
#include <rtgui/kbddef.h>
#include <rtgui/rtgui_server.h>
#include <rtgui/rtgui_system.h>
#define scl_rcc RCC_APB2Periph_GPIOB
#define scl_gpio GPIOB
#define scl_pin GPIO_Pin_6
#define sda_rcc RCC_APB2Periph_GPIOB
#define sda_gpio GPIOB
#define sda_pin GPIO_Pin_7
#define rst_rcc RCC_APB2Periph_GPIOC
#define rst_gpio GPIOC
#define rst_pin GPIO_Pin_6
#define int_rcc RCC_APB2Periph_GPIOC
#define int_gpio GPIOC
#define int_pin GPIO_Pin_9
// iic device address
#define OTT_DEVICE_ADDR_W 0XB2 // Device address for write
#define OTT_DEVICE_ADDR_R 0XB3 // Device address for read
// buffer address
#define OTT_BUFFER_ADDR_SENSOR 0X0D00 // Buffer address for turn on/off sensor
// scale parameter
#define OTT_SCAL_X 0.2963 //screen width/OTT_MAX_X
#define OTT_SCAL_Y 0.32 //screen heigh/OTT_MAX_Y
struct rtgui_touch_device
{
struct rt_device parent;
rt_timer_t poll_timer;
rt_uint16_t x, y;
};
static struct rtgui_touch_device *touch = RT_NULL;
/**
* This function delay for iic clock change
*/
void iic_delay()
{
rt_hw_us_delay(5);
}
/**
* This function will set sda pin to Input/Output mode
*
* @param isInput the value declear for input(1) output(0)
*/
void touch_sda_mode(int isInput)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = isInput ? GPIO_Mode_IPD : GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = sda_pin;
GPIO_Init(sda_gpio, &GPIO_InitStructure);
GPIO_Init(sda_gpio, &GPIO_InitStructure);
}
/**
* This function will generate iic start signal
*/
void iic_start(void)
{
touch_sda_mode(0); //sda pin mode set to output
GPIO_SetBits(sda_gpio, sda_pin);
GPIO_SetBits(scl_gpio, scl_pin);
rt_hw_us_delay(30);
//START:when CLK is high,DATA change form high to low
GPIO_ResetBits(sda_gpio, sda_pin);
iic_delay();
// Hold iic bus for prepare to send or receive data
GPIO_ResetBits(scl_gpio, scl_pin);
}
/**
* This function will generate iic stop signal
*/
void iic_stop(void)
{
touch_sda_mode(0);//sda pin mode set to output
GPIO_SetBits(scl_gpio, scl_pin);
rt_hw_us_delay(30);
//STOP:when CLK is high DATA change form low to high
GPIO_ResetBits(sda_gpio, sda_pin);
iic_delay();
// send iic bus stop signal
GPIO_SetBits(sda_gpio, sda_pin);
rt_hw_us_delay(5);
}
/**
* This function will wait for iic ack signal
*/
u8 iic_wait_ack(void)
{
u8 read_count = 0;
touch_sda_mode(1); //SDA pin mode set to input
GPIO_SetBits(sda_gpio, sda_pin);
GPIO_SetBits(scl_gpio, scl_pin);
while(GPIO_ReadInputDataBit(sda_gpio, sda_pin))
{
if(++read_count>250)
{
iic_stop();
return 1;
}
rt_hw_us_delay(1);
}
GPIO_ResetBits(scl_gpio, scl_pin);
return 0;
}
/**
* This function send a iic ack signal
*/
void iic_send_ack(void)
{
GPIO_ResetBits(scl_gpio, scl_pin);
touch_sda_mode(0);
iic_delay();
GPIO_ResetBits(sda_gpio, sda_pin);
iic_delay();
GPIO_SetBits(scl_gpio, scl_pin);
iic_delay();
GPIO_ResetBits(scl_gpio, scl_pin);
}
/**
* This function send a iic nack signal
*/
void iic_send_nack(void)
{
GPIO_ResetBits(scl_gpio, scl_pin);
touch_sda_mode(0);
iic_delay();
GPIO_SetBits(sda_gpio, sda_pin);
iic_delay();
GPIO_SetBits(scl_gpio, scl_pin);
iic_delay();
GPIO_ResetBits(scl_gpio, scl_pin);
}
/**
* This function will send a byte data to iic bus
* @param value the byte value will be sent
*/
void iic_send_byte(u8 value)
{
u8 i;
touch_sda_mode(0);
GPIO_ResetBits(scl_gpio, scl_pin); // pull down scl pin to start send data
iic_delay();
for(i=0; i<8; i++)
{
GPIO_WriteBit(sda_gpio, sda_pin, (value&0x80)>>7?Bit_SET:Bit_RESET);
value<<=1;
GPIO_SetBits(scl_gpio, scl_pin);
iic_delay();
GPIO_ResetBits(scl_gpio, scl_pin);
iic_delay();
}
}
/**
* This function will read a byte from iic bus
* @retrun the value of readed
*/
u8 iic_read_byte(void)
{
u8 i, result=0;
touch_sda_mode(1);
for(i=0; i<8; i++ )
{
GPIO_ResetBits(scl_gpio, scl_pin);
rt_hw_us_delay(30);
GPIO_SetBits(scl_gpio, scl_pin);
result<<=1;
if(GPIO_ReadInputDataBit(sda_gpio, sda_pin))
{
result++;
}
}
return result;
}
/**
* This function will write values to device buffer(register)
* @param reg the device buffer address
* @param buf the values memery address
* @param size the size of the write values
*
* @return write status, if sucesse return 0
*/
int touch_write_reg(u16 reg, u8 *buf, int size)
{
int i;
int result=0;
iic_start();
iic_send_byte(OTT_DEVICE_ADDR_W);
iic_wait_ack();
iic_send_byte(reg>>8);
iic_wait_ack();
iic_send_byte(reg&0XFF);
iic_wait_ack();
for(i=0;i<size;i++)
{
iic_send_byte(buf);
result=iic_wait_ack();
if(result)break;
}
iic_stop();
return result;
}
/**
* This function will read values from device buffer(register)
* @param reg the device buffer address
* @param buf the values memery address
* @param size the size of the read values
*/
void touch_read_reg(u16 reg, u8 *buf, int size)
{
u8 i;
iic_start();
iic_send_byte(OTT_DEVICE_ADDR_W);
iic_wait_ack();
iic_send_byte(reg>>8);
iic_wait_ack();
iic_send_byte(reg&0XFF);
iic_wait_ack();
iic_start();
iic_send_byte(OTT_DEVICE_ADDR_R);
iic_wait_ack();
for(i=0; i<size - 1; i++)
{
buf=iic_read_byte();
iic_send_ack();
}
// last byte
buf=iic_read_byte();
iic_send_nack();
iic_stop();
}
/**
* This function will turn on/off the touchpad sensor
* @param enable the value of enable(1) or disable(0)
*/
void touch_control_sensor(int enable)
{
unsigned char value=0x00;
if(enable)
{
value=0x80;
}
touch_write_reg(OTT_BUFFER_ADDR_SENSOR, &value, 1);
}
static void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the EXTI9 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
rt_inline void EXTI_Enable(rt_uint32_t enable)
{
EXTI_InitTypeDef EXTI_InitStructure;
/* Configure EXTI */
EXTI_InitStructure.EXTI_Line = EXTI_Line9;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//Falling?????? Rising????
EXTI_InitStructure.EXTI_LineCmd = enable ? ENABLE : DISABLE;
EXTI_Init(&EXTI_InitStructure);
EXTI_ClearITPendingBit(EXTI_Line1);
}
static void EXTI_Configuration(void)
{
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource9);
/* Configure EXTI */
EXTI_Enable(1);
}
void EXTI9_5_IRQHandler(void)
{
/* disable interrupt */
EXTI_Enable(0);
/* start timer */
rt_timer_start(touch->poll_timer);
EXTI_ClearITPendingBit(EXTI_Line9);
}
/**
* This function will read touch coordinator from iic bus,
* then post to rt gui server as mouse event.
* (Note: just process sigle touch, igonre multi touch
*
* @param parameter the value of rt_timer parameter
*/
void touch_timeout(void* parameter)
{
u8 i, values[23];
static unsigned int touched_down = 0;
struct rtgui_event_mouse emouse;
rt_timer_stop(touch->poll_timer);
// read touch data array
touch_read_reg(0, &values[0], 23);
// // debug data output
// for(i=0; i<23; i++)
// {
// rt_kprintf("|%d", values);
// }
// rt_kprintf("|\r\n");
// only process sigle touch, ignore multi touch.
if (values[0] == 0)
{
// when values[0] == 0, that was release touch, hands leaved.
// release mouse up event
emouse.parent.type = RTGUI_EVENT_MOUSE_BUTTON;
emouse.button = (RTGUI_MOUSE_BUTTON_LEFT |RTGUI_MOUSE_BUTTON_UP);
/* use old value */
emouse.x = touch->x;
emouse.y = touch->y;
touched_down = 0;
}
else if (values[0] == 1)
{
// mouse down event
emouse.parent.type = RTGUI_EVENT_MOUSE_BUTTON;
emouse.parent.sender = RT_NULL;
touch->x = (((u16)values[1]<<8) + values[2]) * OTT_SCAL_X;
touch->y = 480 - (((u16)values[3]<<8) + values[4]) * OTT_SCAL_Y;
//rt_kprintf("x:%d y:%d\r\n", touch->x, touch->y);
emouse.x = touch->x;
emouse.y = touch->y;
/* init mouse button */
emouse.button = ((touched_down ? RTGUI_MOUSE_BUTTON_LEFT : RTGUI_MOUSE_BUTTON_RIGHT) |RTGUI_MOUSE_BUTTON_DOWN);
touched_down = 1;
}
else
{
// multi toch, do nothing.
}
if (emouse.parent.type){
/* send event to server */
rtgui_server_post_event(&emouse.parent, sizeof(struct rtgui_event_mouse));
}
EXTI_Enable(1);
}
void touch_hw_init(void)
{
// Enable RCC
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(scl_rcc|sda_rcc|rst_rcc|int_rcc|RCC_APB2Periph_AFIO,ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
// Set SCL
GPIO_InitStructure.GPIO_Pin = scl_pin;
GPIO_Init(scl_gpio, &GPIO_InitStructure);
// Set SDA
GPIO_InitStructure.GPIO_Pin = sda_pin;
GPIO_Init(sda_gpio, &GPIO_InitStructure);
// Set RST
GPIO_InitStructure.GPIO_Pin = rst_rcc;
GPIO_Init(rst_gpio, &GPIO_InitStructure);
// Set INT
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = int_pin;
GPIO_Init(int_gpio, &GPIO_InitStructure);
// Set RST to high
GPIO_SetBits(rst_gpio, rst_pin);
// Pull up INT to high
GPIO_SetBits(int_gpio, int_pin);
// Set SCL and SDA output to high
GPIO_SetBits(scl_gpio, scl_pin);
GPIO_SetBits(sda_gpio, sda_pin);
// Reset touch device
GPIO_ResetBits(rst_gpio, rst_pin);
rt_thread_delay_ms(100);
// Release reset pin
GPIO_SetBits(rst_gpio, rst_pin);
rt_thread_delay_ms(100);
}
/* RT-Thread Device Interface */
static rt_err_t rtgui_touch_init (rt_device_t dev)
{
NVIC_Configuration();
EXTI_Configuration();
return RT_EOK;
}
static rt_err_t rtgui_touch_control (rt_device_t dev, rt_uint8_t cmd, void *args)
{
return RT_EOK;
}
void rtgui_touch_hw_init(void)
{
touch_hw_init();
// Open touch device sensor
touch_control_sensor(1);
{
u8 value = 0;
// Read device status from sensor register
touch_read_reg(OTT_BUFFER_ADDR_SENSOR, &value, 1);
if(value!=0x80)
{
rt_kprintf("Touch initialization failed!\r\nCTP ID:%x\r\n",value);
return;
}
}
touch = (struct rtgui_touch_device*)rt_malloc (sizeof(struct rtgui_touch_device));
if (touch == RT_NULL) return; /* no memory yet */
/* clear device structure */
rt_memset(&(touch->parent), 0, sizeof(struct rt_device));
/* init device structure */
touch->parent.type = RT_Device_Class_Unknown;
touch->parent.init = rtgui_touch_init;
touch->parent.control = rtgui_touch_control;
touch->parent.user_data = RT_NULL;
/* create 1/8 second timer */
touch->poll_timer = rt_timer_create("touch", touch_timeout, RT_NULL,
RT_TICK_PER_SECOND/50, RT_TIMER_FLAG_ONE_SHOT);
rtgui_touch_init(RT_NULL);
/* register touch device to RT-Thread */
rt_device_register(&(touch->parent), "touch", RT_DEVICE_FLAG_RDWR);
}
#ifdef RT_USING_FINSH
#include <finsh.h>
void touch_t( rt_uint16_t x , rt_uint16_t y )
{
struct rtgui_event_mouse emouse ;
emouse.parent.type = RTGUI_EVENT_MOUSE_BUTTON;
emouse.parent.sender = RT_NULL;
emouse.x = x ;
emouse.y = y ;
/* init mouse button */
emouse.button = (RTGUI_MOUSE_BUTTON_LEFT |RTGUI_MOUSE_BUTTON_DOWN );
rtgui_server_post_event(&emouse.parent, sizeof(struct rtgui_event_mouse));
rt_thread_delay(2) ;
emouse.button = (RTGUI_MOUSE_BUTTON_LEFT |RTGUI_MOUSE_BUTTON_UP );
rtgui_server_post_event(&emouse.parent, sizeof(struct rtgui_event_mouse));
}
FINSH_FUNCTION_EXPORT(touch_t, x & y ) ;
#endif[/mw_shl_code]
|