SSブログ

ARIES(STM32F103評価ボード)でタッチパネルを試してみる [ARM&Cortex-M3]

aries_001.png
aries_002.png
aries_003.png
パスワールドさん取り扱いの480×272ピクセルのカラーグラフィックLCDにはタッチパネルが装着されていますので、ユーザーインタフェースとしてこれを使ってみます。

回路図の一部を拡大していますが、40pin FPCケーブルの一部にX軸方向、Y軸方向の端子が出ています。
このタッチパネルは抵抗膜方式で4線式です。抵抗値はX軸方向が600Ω以上、Y軸方向が100Ω以上です。

これをマイコンのポートでドライブし、反対側の軸に接続された端子の出力をADCで変換して読み込む訳です。

イメージとしては2枚目の回路図の感じでしょうか。指で押したところでX軸とY軸が短絡されます。

指で押された時の回路イメージが3枚目の回路図です。例えばX軸方向で中心が押されると、大体300Ωずつに分割されてY軸の抵抗膜に短絡しますので、XRにVCC、XLにGND、YDは600Ωよりも十分に大きな抵抗値のプルアップ抵抗を接続し、YUをADCに接続して変換結果を得ます。

実際には抵抗値は公称値に過ぎないので何等かの方法でキャリブレーションが必要になってくると思います。
運用するならキャリブレーション画面を表示して何箇所かポイントしてその位置のADC変換値を得て、まあSTM32Fのデータ用フラッシュ領域にでも書き込むと言うのが大体の流れでしょうね。


/*************************************************************************/
/* ARIES rev.2                                                           */
/*************************************************************************/
void aries_rev2( void )
{
#define  __X_MAX__  3808
#define  __X_MIN__  258
#define  __Y_MAX__  2099
#define  __Y_MIN__  365
  int i,j,k,r;
  int pos_x,pos_y;
  unsigned short x,y;
  DrawForm df;
  static const struct
  {
    int x;
    int y;
  } xy[] = 
  {
    {99, 29},
    {422,88},
    {477,106},
    {69 ,122},
    {160,69},
    {153,125},
    {361,37},
    {123,53},
    {128,147},
    {175,194},
    {154,224},
    {235,127},
    {402,96},
    {432,4},
    {338,7},
    {265,169},
    {206,62},
    {96 ,80},
    {439,203},
    {413,196},
    {244,169},
    {332,41},
    {338,74},
    {440,127},
    {473,93},
    {140,257},
    {274,27},
    {396,234},
    {231,225},
    {186,80},
    {399,238},
    {366,66},
  };

  static const unsigned short plt[] =
  {
    WHITE,       
//    BLACK,       
    GREY,        
    LIGHTGREY,   
    RED,         
    GREEN,       
    BLUE,        
    YELLOW,      
    SAXEBLUE,    
    MAGENTA,     
    DARKRED,     
    DARKYELLOW,  
    DARKGREEN,   
    DARKSAXEBLUE,
    DARKBLUE,    
    DARKMAGENTA, 
  };

  /*背景色=white*/
//  BG_Set( 0, X_MAX_PIXEL, 0, Y_MAX_PIXEL, BLACK );
  /*シャトル*/
  PutPics( 0, shuttle_Width, 0, shuttle_Height, shuttle_BMPTable );

  TouchPanel_Init();

  for( j = 0, pos_x = pos_y = 4095;; )
  {
    for( i = 0; i < sizeof(xy) / sizeof(xy[0]); i++ )
    {
      for( r = 1; r < Y_MAX_PIXEL / 2; r += 4 )
      {
#if 0
        DrawCircle( xy[i].x, xy[i].y, r, plt[ j ] );
        DrawCircle( xy[i].x, xy[i].y, r + 1, plt[ j ] );
        DrawCircle( xy[i].x, xy[i].y, r + 2, plt[ j ] );
        DrawCircle( xy[i].x, xy[i].y, r + 3, plt[ j ] );
#else
        if( pos_x >= 0 && pos_x < X_MAX_PIXEL && pos_y >= 0 && pos_y < Y_MAX_PIXEL )
        {
          DrawCircle( pos_x, pos_y, r, plt[ j ] );
          DrawCircle( pos_x, pos_y, r + 1, plt[ j ] );
          DrawCircle( pos_x, pos_y, r + 2, plt[ j ] );
          DrawCircle( pos_x, pos_y, r + 3, plt[ j ] );
        }
#endif

//        BG_Set( 0, X_MAX_PIXEL, 0, Y_MAX_PIXEL, BLACK );
//        PutPics( 0, shuttle_Width, 0, shuttle_Height, shuttle_BMPTable );
        PutPics( 0, shuttle_Width, 0, shuttle_Height - 60, shuttle_BMPTable );

//      Wait17ms( 4 );
      }

      if( ++j >= sizeof(plt) / sizeof(plt[0]) ) j = 0;

      /*xとyの移動平均を求める*/
      for( k = 0,x = 0; k < sizeof(ave_x_tbl) / sizeof(ave_x_tbl[0]); k++ )
	  {
        if( ave_x_tbl[ k ] >= 3900 )
        {
          x = 4095 * 16;
          break;
        }
        x += ave_x_tbl[ k ];
	  }
      x >>= 4;

      for( k = 0,y = 0; k < sizeof(ave_y_tbl) / sizeof(ave_y_tbl[0]); k++ )
	  {
        if( ave_y_tbl[ k ] >= 3900 )
        {
          y = 4095 * 16;
          break;
        }
        y += ave_y_tbl[ k ];
	  }
      y >>= 4;

      FourNineDisplay( (480 / 2) - 10 - (38 * 4), 272 - 60, x );
      FourNineDisplay( (480 / 2) + 10, 272 - 60, y );
      pos_x = ((__X_MAX__ - x) * 10) / (((__X_MAX__ - __X_MIN__) * 10) / X_MAX_PIXEL);
      pos_y = ((__Y_MAX__ - y) * 10) / (((__Y_MAX__ - __Y_MIN__) * 10) / Y_MAX_PIXEL);

      IWDG_WriteAccessCmd( 0xaaaa );  /*IWDG延長*/
    }
  }
}

/*************************************************************************/
/* タッチパネルのADC初期化                                               */
/*************************************************************************/
void TouchPanel_Init( void )
{
  /*ADC1へクロックの供給開始*/
  RCC_APB2PeriphClockCmd( RCC_APB2Periph_ADC1, ENABLE );
  RCC_APB2PeriphResetCmd( RCC_APB2Periph_ADC1, DISABLE );
  RCC->CFGR |= (3 << 14);  /*PCLK2を8分周*/

  if( !(ADC1->CR2 & 0x00000001) ) ADC1->CR2 |= 0x00000001;  /*ADON*/
  ADC1->CR2 |= 0x00000004;          /*較正開始*/
  while( ADC1->CR2 & 0x00000004) ;  /*較正完了待ち*/
  ADC_Calibration_Value = ADC1->DR;  /*較正値の読み出し*/
  ADC1->CR2 |= (7 << 17);           /*ソフトウエア変換を選択*/
  ADC1->SMPR2 = 3 << 0;             /*サンプリングタイミング=28.5サイクル*/
  ADC1->SQR1 = (0 << 20);           /*レギュラー変換グループの項目数=1*/
}

/*************************************************************************/
/* タッチパネルのX側の読み出し                                           */
/* PC0(IN10)がUP、PC1(IN11)がDOWN、PC2(IN12)がRIGHT、PC3(IN13)がLEFT。   */
/*************************************************************************/
unsigned short TouchPanel_X_Read( void )
{
  volatile unsigned short temp;

  LEFT_HI;  /*左端をHI、右端をLOとする*/
  RIGHT_LO;

  GPIO_Terminal_Init( GPIOC, GPIO_Speed_2MHz, GPIO_Mode_Out_PP, GPIO_Pin_3 | GPIO_Pin_2 );  /*RIGHTとLEFTを出力に*/
  GPIO_Terminal_Init( GPIOC, GPIO_Speed_2MHz, GPIO_Mode_AIN, GPIO_Pin_0 );  /*PC0(IN10)をアナログ入力に*/
  GPIO_Terminal_Init( GPIOC, GPIO_Speed_2MHz, GPIO_Mode_IPU, GPIO_Pin_1 );  /*PC1をプルアップ付き入力に*/
  PC_ODR |= 0x0002;

  ADC1->SQR3 = (10 << 0);           /*ADC10の変換位置*/

  ADC1->CR2 |= (1 << 22);           /*ソフトウエア変換開始*/
  ADC1->CR2 |= 0x00000001;          /*ADON*/
  while( !(ADC1->SR & 0x00000002) ) ;  /*変換完了待ち*/
  temp = ADC1->DR - ADC_Calibration_Value;  /*変換完了後の読み出し*/
  /*2回行う*/
  ADC1->CR2 |= (1 << 22);           /*ソフトウエア変換開始*/
  ADC1->CR2 |= 0x00000001;          /*ADON*/
  while( !(ADC1->SR & 0x00000002) ) ;  /*変換完了待ち*/
  temp = ADC1->DR - ADC_Calibration_Value;  /*変換完了後の読み出し*/

  RIGHT_LO;  /*電気食うので電圧の印加を停止*/
  LEFT_LO;

  return temp & 0x0fff;
}

/*************************************************************************/
/* タッチパネルのY側の読み出し                                           */
/* PC0(IN10)がUP、PC1(IN11)がDOWN、PC2(IN12)がRIGHT、PC3(IN13)がLEFT。   */
/*************************************************************************/
unsigned short TouchPanel_Y_Read( void )
{
  volatile unsigned short temp;

  UP_HI;  /*上端をHI、下端をLOとする*/
  DOWN_LO;

  GPIO_Terminal_Init( GPIOC, GPIO_Speed_2MHz, GPIO_Mode_Out_PP, GPIO_Pin_1 | GPIO_Pin_0 );   /*UPとDOWNを出力に*/
  GPIO_Terminal_Init( GPIOC, GPIO_Speed_2MHz, GPIO_Mode_AIN, GPIO_Pin_3 );  /*PC3(IN13)をアナログ入力に*/
  GPIO_Terminal_Init( GPIOC, GPIO_Speed_2MHz, GPIO_Mode_IPU, GPIO_Pin_2 );  /*PC2をプルアップ付き入力に*/
  PC_ODR |= 0x0004;

  ADC1->SQR3 = (13 << 0);           /*ADC13の変換位置*/

  ADC1->CR2 |= (1 << 22);           /*ソフトウエア変換開始*/
  ADC1->CR2 |= 0x00000001;          /*ADON*/
  while( !(ADC1->SR & 0x00000002) ) ;  /*変換完了待ち*/
  temp = ADC1->DR - ADC_Calibration_Value; /*変換完了後の読み出し*/
  /*2回行う*/
  ADC1->CR2 |= (1 << 22);           /*ソフトウエア変換開始*/
  ADC1->CR2 |= 0x00000001;          /*ADON*/
  while( !(ADC1->SR & 0x00000002) ) ;  /*変換完了待ち*/
  temp = ADC1->DR - ADC_Calibration_Value; /*変換完了後の読み出し*/

  UP_LO;  /*電気食うので電圧の印加を停止*/
  DOWN_LO;

  return temp & 0x0fff;
}

/*************************************************************************/
/* TE割込みハンドラから呼ばれる。                                        */
/*************************************************************************/
void ARIES_GLCD_Int_Hdr( void )
{
  unsigned short x,y;
  static int wptr;

  x = TouchPanel_X_Read();
  y = TouchPanel_Y_Read();

  ave_x_tbl[ wptr ] = x;
  ave_y_tbl[ wptr ] = y;

  if( ++wptr >= sizeof(ave_x_tbl) / sizeof(ave_x_tbl[0]) ) wptr = 0;
}


※タッチパネルを動かすのにELMさんのページを参考にさせて頂きました。
http://elm-chan.org/index_j.html







nice!(0)  コメント(0)  トラックバック(0) 

nice! 0

コメント 0

コメントを書く

お名前:[必須]
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

※ブログオーナーが承認したコメントのみ表示されます。

トラックバック 0

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。