めんどくさいAVRのレジスタアクセス(ビット演算)を解決します。
AVRのレジスタ操作はめんどくさい
AVRでのレジスタ操作はとてもめんどくさいです。
ある特定のビットだけ操作したい場合などは特にめんどくさいです。
以下のようなマクロを組み合わせて、がんばって設定することになると思います。
1. |
2. |
3. |
4. |
5. |
6. |
7. |
8. |
9. |
10. |
11. |
12. |
13. |
14. |
|
|
PORTD |= _BV(0); |
? |
|
PORTD &= ~_BV(1); |
? |
|
PORTD &= ~(_BV(1) | _BV(2) ); |
? |
|
if( bit_is_set( PIND, 1 )){ nop(); } |
? |
|
loop_until_bit_is_set( PIND, 2 ); |
|
これは直感的にわかりずらく、なんとか解決したいです。
しかも潜在的にリードモディファイライト処理になる場合が多く、
微妙なタイミングで発生する、発見しづらい不具合に繋がりやすいです。
自分でI/Oアドレスをマッピングしてしまおう
掲題のとおり自分でマッピングしてしまうことで全て解決します。
ここではマッピングの仕方について記述します。以下を参考にして下さい。
1. |
2. |
3. |
4. |
5. |
6. |
7. |
8. |
9. |
10. |
11. |
12. |
13. |
14. |
15. |
16. |
17. |
18. |
19. |
20. |
21. |
22. |
23. |
24. |
25. |
26. |
27. |
28. |
29. |
30. |
31. |
32. |
|
|
|
|
typedef union{ |
|
unsigned char all : 8; |
? |
|
struct{ |
unsigned char b0 : 1; |
unsigned char b1 : 1; |
unsigned char b2 : 1; |
unsigned char b3 : 1; |
unsigned char b4 : 1; |
unsigned char b5 : 1; |
unsigned char b6 : 1; |
unsigned char b7 : 1; |
}bit; |
}SFR8; |
? |
|
|
|
|
#define R_PIND (*(volatile SFR8 *)0x29u) |
? |
|
#define R_DDRD (*(volatile SFR8 *)0x2Au) |
? |
|
#define R_PORTD (*(volatile SFR8 *)0x2Bu) |
? |
|
マッピングしたレジスタのアクセス方法
こうやってアクセスできます。ちょー便利。
1. |
2. |
3. |
4. |
5. |
6. |
7. |
8. |
9. |
10. |
11. |
12. |
13. |
14. |
15. |
16. |
|
int main( void ) |
{ |
|
R_DDRD.all = 0xFFu; |
? |
|
R_DDRD.bit.b1 = 1u; |
? |
|
R_PORTD.all = 0x00u; |
? |
|
if( R_PIND.bit.b1 ){ |
DEBUG_MSG("PORTD.1 is Hi-Level!!"); |
} |
} |
|
複数ビットのアクセス
ビットフィールドでマッピングしているので、以下のように複数ビットのアクセスも簡単です。
1. |
2. |
3. |
4. |
5. |
6. |
7. |
8. |
9. |
10. |
11. |
12. |
13. |
14. |
15. |
16. |
17. |
18. |
19. |
20. |
21. |
22. |
23. |
24. |
25. |
26. |
27. |
28. |
29. |
30. |
31. |
32. |
33. |
34. |
35. |
36. |
37. |
38. |
39. |
40. |
41. |
|
|
|
|
#define R_CLKPR (*(volatile CS_CLKPR *)0x61u) |
typedef union{ |
|
unsigned char all; |
? |
|
SFR8 byte; |
? |
|
struct{ |
|
unsigned char B_CLKPCE : 4; |
|
unsigned char reserve : 3; |
|
unsigned char B_CLKPS : 1; |
}bit; |
}CS_CKLPR; |
? |
|
|
|
int main( void ) |
{ |
|
R_CLKPR.bit.B_CLKPS = 1u; |
? |
|
R_CLKPR.bit.B_CLKPCE = 0u; |
R_CLKPR.bit.B_CLKPCE = 1u; |
R_CLKPR.bit.B_CLKPCE = 2u; |
.. |
R_CLKPR.bit.B_CLKPCE = 10u; |
? |
? |
|
R_CKLPR.byte.bit.b7 = 1; |
} |
|