⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 f2013-touchkey.c

📁 这写C源代码是MSP430单片机的应用程序
💻 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 + -