📄 f2013-touchkey.c
字号:
//******************************************************************************
// MSP430xG461x Demo -Touchpad demonstration for the "4" on the 2006 ATC board.
//
// Description: A program for the MSP430FG4619 on the 2006 ATC board
// to accept I2C information from the touchpad,display it numerically
// on the LCD, and send it to a host PC for graphical display.This demo
// connects two MSP430's via the I2C bus. The masterreceives one byte
// from the slave. This is the master code. It receivesa single byte as
// soon as a button connected on P1.0 was pressed.
// ACLK = 32kHz, MCLK = SMCLK = TACLK = BRCLK = 1MHz
//
// THIS IS THE MASTER CODE
//
// MSP430F2013 MSP430xG461x
// slave master
// ----------------- ------------------
// -|XIN SDA/P1.7|<------->|P3.1/UCB0SDA XIN|-
// 32kHz | | | | 32kHz
// -|XOUT | | XOUT|-
// | SCL/P1.6|<------->|P3.2/UCB0SCL P2.4|----
// | | | | 9600
// | | | P2.5|----
// Note: internal pull-ups are used in this example for SDA & SCL
//
// FengLF
// LSD SCIENCE& TECHNOLOGY CO.,LTD
// 2007.07
// Built with IAR Embedded Workbench Version: 3.42A
//******************************************************************************
#include <stdint.h>
#include <stdlib.h>
#include <msp430x20x3.h>
#define FALSE 0
#define TRUE (!FALSE)
typedef struct
{
unsigned char port;
unsigned char port_bit;
int threshold;
} key_line_config_data_t;
typedef struct
{
int base_capacitance;
int filtered;
} key_line_data_t;
#define ADAPTION_RATE 1000
#define ADAPTION_RATIO 50
#define KEY_DOWN_THRESHOLD 12
#define KEY_UP_THRESHOLD 12
#define NUM_KEYS 16
#define NUM_LINES 8
#define DIRECTIONAL_HYSTERESIS 6
const key_line_config_data_t key_line_config[NUM_LINES] =
{
{1, BIT0, 40},
{1, BIT1, 40},
{1, BIT2, 40},
{1, BIT3, 40},
{1, BIT4, 40},
{1, BIT5, 40},
{2, BIT6, 40},
{2, BIT7, 40},
};
const uint8_t map_key_to_sense[NUM_KEYS] =
{
2, 3, 1, 6,
5, 2, 7, 6,
1, 4, 3, 0,
5, 4, 0, 7
};
const uint8_t map_sense_to_key[NUM_KEYS][2] =
{
{11, 14},
{2, 8},
{0, 5},
{1, 10},
{9, 13},
{4, 12},
{3, 7},
{6, 15}
};
key_line_data_t key_line[NUM_LINES];
unsigned int timer_count;
void usi_i2c_init(void);
void send_to_host(int position);
uint8_t test_seq_data = 0;
uint8_t host_data = 0;
void init_key(key_line_data_t *key_line, const key_line_config_data_t *key_line_config)
{
key_line->base_capacitance = 0;
key_line->filtered = 0;
if (key_line_config->port == 1)
{
P1OUT &= ~key_line_config->port_bit;
P1DIR |= key_line_config->port_bit;
P1IES |= key_line_config->port_bit;
}
else
{
P2OUT &= ~key_line_config->port_bit;
P2DIR |= key_line_config->port_bit;
P2IES |= key_line_config->port_bit;
}
}
unsigned int measure_key_capacitance(int key_no)
{
char active_key;
const key_line_config_data_t *keyp;
const key_line_config_data_t *partner;
int sum;
keyp = &key_line_config[key_no];
partner = &key_line_config[key_no ^ 1];
active_key = keyp->port_bit;
if (keyp->port == 1)
P1OUT |= active_key;
else
P2OUT |= active_key;
_NOP();
_NOP();
_NOP();
if (keyp->port == 1)
{
P1IES |= active_key;
P1IE |= active_key;
P1DIR &= ~active_key;
}
else
{
P2IES |= active_key;
P2IE |= active_key;
P2DIR &= ~active_key;
}
timer_count = TAR;
LPM0;
if (keyp->port == 1)
{
P1IE &= ~active_key; // 关中断
P1OUT &= ~active_key; // 输出低电平
P1DIR |= active_key; // 输出方向
}
else
{
P2IE &= ~active_key; // 关中断
P2OUT &= ~active_key; // 输出低电平
P2DIR |= active_key; // 输出方向
}
sum = timer_count;
active_key = keyp->port_bit;
if (partner->port == 1)
P1OUT |= partner->port_bit;
else
P2OUT |= partner->port_bit;
_NOP();
_NOP();
_NOP();
if (keyp->port == 1)
{
P1IES &= ~active_key; // 下降沿中断
P1IE |= active_key; // 中断使能
P1DIR &= ~active_key; // 输入方向
}
else
{
P2IES &= ~active_key; // 下降沿中断
P2IE |= active_key; // 中断使能
P2DIR &= ~active_key; // 输入方向
}
timer_count = TAR;
LPM0;
if (keyp->port == 1)
{
P1IE &= ~active_key; // 关中断
P1OUT &= ~active_key; // 输出低电平
P1DIR |= active_key; // 输出方向
}
else
{
P2IE &= ~active_key; // 关中断
P2OUT &= ~active_key; // 输出低电平
P2DIR |= active_key; // 输出方向
}
if (partner->port == 1)
P1OUT &= ~partner->port_bit;
else
P2OUT &= ~partner->port_bit;
sum += timer_count;
return sum >> 1;
}
int scan_keys(void)
{
int i;
int margin;
for (i = 0; i < NUM_LINES; i++)
{
margin = measure_key_capacitance(i) - key_line[i].base_capacitance;
key_line[i].filtered += (margin - (key_line[i].filtered >> 4));
}
return 0;
}
int last_peak = -100;
long int aaa;
long int bbb;
int min;
int grass_level;
void xxxx(int line, int key)
{
if ((key_line[line].filtered - min) > grass_level)
{
aaa += (key_line[line].filtered - min);
bbb += key*(key_line[line].filtered - min);
}
}
int find_finger_position(void)
{
int i;
int j;
int k;
int l;
long int a;
long int b;
int max;
int max_pos;
min = 32767;
max = -32768;
max_pos = -1;
for (i = 0; i < NUM_LINES; i++)
{
if (key_line[i].filtered < min)
min = key_line[i].filtered;
if (key_line[i].filtered > max)
{
max = key_line[i].filtered;
max_pos = i;
}
}
if (max < 100)
return -1;
grass_level = (max - min) >> 3;
i = map_sense_to_key[max_pos][0];
j = map_sense_to_key[max_pos][1];
if (abs(last_peak - j) > abs(last_peak - i))
{
if (last_peak < 12 || i != 2)
j = i;
}
aaa = 0;
bbb = 0;
if (last_peak >= 12 && i == 2)
{
last_peak = 13;
xxxx(4, 13);
xxxx(1, 14);
xxxx(0, 15);
}
else
{
last_peak = j;
k = j - 1;
if (k < 0)
k = 0;
l = j + 1;
if (l >= NUM_KEYS)
l = NUM_KEYS - 1;
for (i = k; i <= l; i++)
{
j = map_key_to_sense[i];
xxxx(j, i + 1);
}
}
a = aaa;
b = bbb;
b /= (a >> 4);
b -= 16;
if (b < 0)
b = 0;
return b;
}
int last_position = 0;
int new_position = 0;
int button_down = 0;
void main(void)
{
int i;
WDTCTL = WDTPW | WDTHOLD;
BCSCTL3 = LFXT1S_2;
BCSCTL1 = CALBC1_16MHZ;
DCOCTL = CALDCO_16MHZ;
_BIS_SR(OSCOFF);
P1OUT = 0;
P1DIR = 0xFF;
P1SEL = 0;
P1REN = 0;
P2OUT = 0;
P2DIR = 0xFF;
P2SEL = 0;
P2REN = 0;
usi_i2c_init();
_EINT();
#if 0
for (;;)
{
send_to_host(test_seq_data++);
for (i = 0; i < 15000; i++)
_NOP();
}
#endif
for (i = 0; i < NUM_LINES; i++)
init_key(&key_line[i], &key_line_config[i]);
TACTL = TASSEL_2 | MC_2 | ID_3;
for (i = 0; i < 100; i++)
scan_keys();
for (i = 0; i < NUM_LINES; i++)
{
key_line[i].base_capacitance = key_line[i].filtered >> 4;
key_line[i].filtered = 0;
}
for (;;)
{
scan_keys();
if ((new_position = find_finger_position()) >= 0)
{
if (new_position > last_position + DIRECTIONAL_HYSTERESIS
||
new_position < last_position - DIRECTIONAL_HYSTERESIS)
{
if (new_position > last_position)
last_position = new_position - (DIRECTIONAL_HYSTERESIS - 1);
else
last_position = new_position + (DIRECTIONAL_HYSTERESIS - 1);
if (new_position < 240)
send_to_host(new_position);
else
send_to_host(239);
}
}
else
{
last_position = -100;
}
}
}
#pragma vector=PORT1_VECTOR
__interrupt void port_1_interrupt(void)
{
P1IFG = 0; // 清中断标志位
timer_count = TAR - timer_count; // 记录电容放电时间
LPM3_EXIT; // 退出低功耗
}
#pragma vector=PORT2_VECTOR
__interrupt void port_2_interrupt(void)
{
P2IFG = 0; // 清中断标志位
timer_count = TAR - timer_count; // 记录电容放电时间
LPM3_EXIT; // 退出低功耗
}
#pragma vector=TIMERA0_VECTOR
__interrupt void timera0_interrupt(void)
{
LPM3_EXIT;
}
#pragma vector=TIMERA1_VECTOR
__interrupt void timera1_interrupt(void)
{
switch (TAIV)
{
case 2:
LPM3_EXIT;
break;
}
}
const uint8_t SLV_Addr = 0x48; // I2C从机地址 0x48
int8_t I2C_state = -2;
void send_to_host(int data)
{
host_data = data;
I2C_state = 0;
USICTL1 |= USIIFG; // 置标志位
do
LPM0;
while (I2C_state >= 0);
}
void usi_i2c_init(void)
{
P1OUT |= (BIT7 | BIT6); // P1.6、P1.7设置成I2C功能
P1REN |= (BIT7 | BIT6); // 使能 SDA、SDL
USICTL0 = USIPE6 | USIPE7 | USIMST | USISWRST; // 设置成 I2C模式
USICTL1 = USII2C | USIIE; // 使能I2C模式,开中断
USICKCTL = USIDIV_7 | USISSEL_2 | USICKPL; // 设置 USI 时钟 SCL = SMCLK/128 (~125kHz)
USICNT |= USIIFGCC; // 禁止自动清标志位
USICTL0 &= ~USISWRST; // 使能 USI
USICTL1 &= ~USIIFG; // 清标志位
}
#pragma vector = USI_VECTOR
__interrupt void USI_TXRX(void)
{
switch (__even_in_range(I2C_state, 10))
{
case 0:
P1OUT |= 0x01;
USISRL = 0x00; // 产生起始条件
USICTL0 |= (USIGE | USIOE); // 输出使能
USICTL0 &= ~USIGE; // 关闭输出锁存
USISRL = SLV_Addr << 1;
USICNT = (USICNT & 0xE0) + 0x08; // 8位数据
I2C_state = 2; // 跳转到下一个状态
break;
case 2:
USICTL0 &= ~USIOE; // SDA输入
USICNT |= 0x01; // 数据长度为1 ,复位状态
I2C_state = 4; // 跳转到下一个状态
break;
case 4:
USICTL0 |= USIOE; // SDA 输出使能
if (USISRL & 0x01)
{
USISRL = 0x00; // 写入数据0
USICNT |= 0x01; // SCL 高, SDA 低
I2C_state = 10; // 跳转到下一个状态
P1OUT |= 0x01; // 关闭 LED
}
else
{
USISRL = host_data; // 发送数据到从机
USICNT |= 0x08; // 8 位数据,开始发送
I2C_state = 6; // 跳转到下一个状态
P1OUT &= ~0x01; // 关闭 LED
}
break;
case 6:
USICTL0 &= ~USIOE; // SDA 输入,接收数据
USICNT |= 0x01; // 1 位数据,开始接收
I2C_state = 8; // 跳转到下一个状态
break;
case 8:
USICTL0 |= USIOE;
if (USISRL & 0x01)
{
}
else
{
}
USISRL = 0x00;
USICNT |= 0x01; // 1 位数据 SCL 高, SDA 低
I2C_state = 10; // 跳转到下一个状态
break;
case 10:
USISRL = 0x0FF; // USISRL = 1
USICTL0 |= USIGE; // 输出使能
USICTL0 &= ~(USIGE | USIOE); // 禁止输出锁存、发送
I2C_state = -2; // 状态复位,准备下次发送数据
LPM0_EXIT; // 退出低功耗
break;
}
USICTL1 &= ~USIIFG; // 清标志位 USIIFG
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -