実例30  複数の外部ピン割り込みを処理するには?
 ----GPIO割り込み----


GPIOがたくさんあるのはすでにおわかりと思います.
そいつらを割り込み入力ピンとして使ってしまおうといのがこのページでやることです.

けれど、全てのGPIO割り込みに使えるかというとそうではありません.まず下図で概要を説明します.
外部ピン
割り込みルーチン
割り込みタイプ
PA[6:2] void 関数名( void ) interrupt 3
EXTI_SENSITIVITY_FALL_LOW  → negativeエッジかつLOWで割り込み発生
EXTI_SENSITIVITY_RISE_ONLY  →positiveエッジで割り込み発生
EXTI_SENSITIVITY_FALL_ONLY  →negativeエッジで割り込み発生
EXTI_SENSITIVITY_RISE_FALL  →positiveエッジまたはnegativeエッジで割り込み発生
PB[7:0] void 関数名( void ) interrupt 4
PC[7:0] void 関数名( void ) interrupt 5
PD[6:0] void 関数名( void ) interrupt 6
PE[7:0] void 関数名( void ) interrupt 7
PD7  (TLI) void 関数名( void ) interrupt 0 EXTI_TLISENSITIVITY_FALL_ONLY  →TLIはnegativeエッジで割り込み発生
EXTI_TLISENSITIVITY_RISE_ONLY 
→TLIはpositiveエッジで割り込み発生

第1列
割り込み可能な外部ピンです.
PD7だけはちょっと扱いが異なっていて、最高レベルの割り込み(TLI)に割り当てられています.


第2列
外部ピンごとに割り込み番号がちがいます.
したがって、割り込みルーチンの宣言の仕方も異なります.
TLIはその名(Top Level Interrupt)示すとおり、割り込み番号0なので最優先の割り込みです.
TLIは非常停止などに使われることを想定していると思われます.

第3列
割り込みピンの信号がどういうふうに変化したら割り込みがかかるのかを設定できます.
EXTI_SENSITIVITY_FALL_ONLY がポピュラーだと思います.
なぜかというと、割り込みピンはプルアップしておき、割り込み発生源がLOWに落ちたときに割り込み発生という使い方が多いからです.

STM8S-DISCOVERYのピン配置



作るプログラムの仕様を決めます

LEDをチカチカさせます.
TLIを
をGNDに一瞬接触させると、割り込みがかかって、LEDが8Hzでチカチカするようになります.
PA6をGNDに一瞬接触させると、割り込みがかかって、LEDが4Hzでチカチカするようになります
PA5をGNDに一瞬接触させると、割り込みがかかって、LEDが2Hzでチカチカするようになります
PA4をGNDに一瞬接触させると、割り込みがかかって、LEDが1Hzでチカチカするようになります





ソースコードの解説

サンプルプログラムをこちらに置いてあります

下記はmain.cです.

●#include "stm8s.h"
ライブラリを利用するためにインクルードします.

●@CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSI, DISABLE, CLK_CURRENTCLOCKSTATE_DISABLE);
ACLK_HSIPrescalerConfig( CLK_PRESCALER_HSIDIV1 );
BCLK_SYSCLKConfig( CLK_PRESCALER_CPUDIV1 );
@は内部クロックの16MHzをつかうように設定します.
Aは16MHzを1分周して(=分周せずに)fMASTER=16MHzに設定します.fMASTERはタイマに供給されます.
BはfMASTERを1分周して(=分周せずに)fCPU=16MHzに設定します.fCPUはCPUに供給されます.
クロック設定についてはこちらのページを参照して思い出してください.

●GPIO_DeInit(GPIOA);
GPIO_Init(GPIOA, GPIO_PIN_4, GPIO_MODE_IN_PU_IT);
GPIO_Init(GPIOA, GPIO_PIN_5, GPIO_MODE_IN_PU_IT);
GPIO_Init(GPIOA, GPIO_PIN_6, GPIO_MODE_IN_PU_IT);
外部割り込みピンにしたいPA4,PA5,PA6を入力に設定しています.
とくに GPIO_MODE_IN_PU_IT が重要です.
IN=inputの意味.
PU=pullupの意味.STM8Sの内蔵抵抗でプルアップされます.
IT=Interruptの略で、すなわち割り込みにこのピンを使うと宣言しています.
GPIOについてはこちらのページを参照して思い出してください.

●GPIO_DeInit(GPIOD);
CGPIO_Init(GPIOD, GPIO_PIN_0, GPIO_MODE_OUT_PP_HIGH_FAST); // LED
DGPIO_Init(GPIOD, GPIO_PIN_7, GPIO_MODE_IN_PU_IT); // TLI
CLEDが接続されているポートを出力に設定しています.
DTLIポートであるPD7を入力に設定しています.
GPIO_MODE_IN_PU_ITです.

●EXTI_DeInit();
EEXTI_SetExtIntSensitivity( EXTI_PORT_GPIOA, EXTI_SENSITIVITY_FALL_ONLY );
FEXTI_SetTLISensitivity( EXTI_TLISENSITIVITY_FALL_ONLY );
E外部割り込みに設定した PA4,PA5,PA6 をひっくるめてGPIOA として、割り込みタイプをnegativeエッジに設定しています.
FTLIに設定したPD7の
割り込みタイプをnegativeエッジに設定しています.
TLIだけ別関数の特別扱いなのです.

●TIM4_DeInit();
TIM4_TimeBaseInit( TIM4_PRESCALER_128, 255 ); // 16MHz/128/256=488Hz
TIM4_ITConfig(TIM4_IT_UPDATE, ENABLE);
TIM4_Cmd(ENABLE);
タイマTIM4を利用して、488Hzで定期的割り込みをかけています.
LEDの点滅周期を決定する源としてTIM4を活用しています.

●int cnt_max=122;
void TLI_interrupt(void) interrupt 0  {    cnt_max=30;   }
TLI割り込みルーチンです.TLIのnegativeエッジでここに飛んできます.
やっていることは、点滅周期を決める cnt_max という変数に30を書き込んでいるだけです.

●void GPIOA_interrupt(void) interrupt 3   {
    if(GPIO_ReadInputPin( GPIOA, GPIO_PIN_4 )==0) cnt_max=244;
    if(GPIO_ReadInputPin( GPIOA, GPIO_PIN_5 )==0) cnt_max=122;
    if(GPIO_ReadInputPin( GPIOA, GPIO_PIN_6 )==0) cnt_max=61;   }
PA4,PA5,PA6の割り込みルーチンです.
PA4,PA5,PA6のnegativeエッジでここに飛んできます.
やっていることは、
LOWになっているのがPA4なら、点滅周期を決める cnt_max という変数に244を書き込んでいます.
LOWになっているのがPA5なら、点滅周期を決める cnt_max という変数に122を書き込んでいます.
LOWになっているのがPA6なら、点滅周期を決める cnt_max という変数に61を書き込んでいます.

●int cnt=0;
void TIM4_interrupt(void) interrupt 23  {
    cnt++;
    if(cnt>cnt_max)    {
        GPIO_WriteReverse(GPIOD, GPIO_PIN_0);
        cnt=0;
    }
    TIM4_ClearFlag(TIM4_FLAG_UPDATE);
}
タイマTIM4の割り込みルーチンです.
488Hzでここに飛んできます.
LEDを点滅させますが、点滅周期を目に見えるくらいまで遅くするために cnt という変数をつかって点滅周期を遅くしています.
割り込みの度にcntがインクリメントされ、TLI割り込みルーチンとGPIOA割り込みルーチンで設定されたcnt_maxまで0からカウントします.
結果として、cnt_maxが244なら1HzでLEDが点滅し、cnt_maxが30なら8HzでLEDが点滅します.

inserted by FC2 system