メニュー
▼ アクセス(地図)
▼ Windowsアプリ開発 ▼ マイコン開発 ▼ CGI・PHP制作 |
▼ サイトマップ(全投稿記事)
▼ タイトル(画像一覧) ▼ 事業内容 |
お問い合わせメールフォームが開きます。
2009年04月29日
PIC12F675でエレキー
今回は、Microchip社の8Pinマイコン・PIC12F675でエレキー(アマチュア無線用)を作ってみました。
エレキープロジェクト第8ステージとなりました。
PIC12F675は、秋月電子さんでは130円で販売されているA/Dコンバータ内臓のマイコンです。
小型安価のため、いろいろと利用価値があります。
http://akizukidenshi.com/catalog/g/gI-02113/
Webサイトを検索したところ
PICマイコン、C言語、フリーのCコンパイラ
で作られたエレキーのサンプルソースコードがなかったため、今回の試作・公開となりました。
参考にしていただければ幸いです。
Cコンパイラはフリーの SDCC(Small Device C Compiler)
アセンブラ・リンカもフリーの gputils(GNU PIC Utilities)を使用しました。
上記ソフトウエアのインストール方法と簡単な使用方法は、次のサイトにわかりやすい説明がありますのでご参照ください。
SDCCの使い方(http://xenopusq.hp.infoseek.co.jp/pic/sdcc.html)
SDCCとgputilsのインストール
マイコン動作は、以前の記事「エレキープロジェクト・UML設計図」に基づいています。
ポート配置と配線はこちらです。
(今回の配線はブレッドボードを使用してみました。)
LED出力 → GP5(負論理)回路図は下記の通りです。
Buzzer出力 → GP4(Trバッファ付き)
Dot入力 → GP1(内部プルアップ抵抗)
Dash入力 → GP2(内部プルアップ抵抗)
速度調整 → AN0(VR入力)
ソフトウエア機能としては下記を使用しています。
A/D変換
タイマ(0)割り込み
ポートの入出力/内臓プルアップ機能
PIC12F675のデータシート(英文)はこちら
http://ww1.microchip.com/downloads/en/devicedoc/41190c.pdf
PIC12F629でもエレキー作ってみました。 下記記事をご参照ください。
http://micom.hamazo.tv/e1848478.html
動作の様子はこちら
コンパイル時のパラメータは下記のようにしました。(pic12f675_elekey.c はソースファイル名)
> sdcc -V -c -mpic14 -p12f675 pic12f675_elekey.c
> gplink -I"c:\program files\SDCC\lib\pic" -w -r -o pic12f675_elekey pic12f675_elekey.o libsdcc.lib pic12f675.lib
ソースコードはこちらです。
(上記のSDCCの環境でコンパイル(HEX作成)可能です。)
//--------------------------------------------------------------------
//
// Simple Elekey Program
//
// DESCRIPTION:
// Hardware: Microchip PIC 12F675
// C-Compoler: SDCC(Small Device C Compiler)
// Editer: M.Utsunomiya
// Date: 2009/4/29
//
//--------------------------------------------------------------------
//----I/O DESCRIPTION ------------------------------------------------
// 実機レイアウト・配線
// LED出力 → GP5(負論理)
// Buzzer出力 → GP4(Trバッファ)
// Dot入力 → GP1(内部プルアップ抵抗)
// Dash入力 → GP2(内部プルアップ抵抗)
// 速度調整 → AN0(VR入力)
//--------------------------------------------------------------------
#include <sdcc-lib.h>
#include <pic12f675.h>
//----------------------------------------------------------------------------
// Define Code Parameter
//----------------------------------------------------------------------------
#define PARA_ALL_OFF 0x00
#define PARA_DOT_ON 0x01
#define PARA_DOT_OFF 0x02
#define PARA_DASH_ON 0x03
#define PARA_DASH_OFF 0x04
#define LIMIT_VALUE 0x03 // チャタリングフィルタ用
#define MAX_SPEED 5
#define MIN_SPEED 15
//----------------------------------------------------------------------------
// Define User Memory
//----------------------------------------------------------------------------
unsigned int ParaTime;
unsigned int ADCData;
unsigned char Timer100ms;
unsigned char ParaCode;
unsigned char CntDotOn;
unsigned char CntDashOn;
//--------------------------------------------------------------------
// Configuration Bits (pic12f675.h 内で定義)
//--------------------------------------------------------------------
// _CPD_ON / _CPD_OFF : Data Code Protection
// _CP_ON / _CP_OFF : Code Protection
// _BODEN_ON / _BODEN_OFF : Brown-out(低電圧) Detect Enable
// _MCLRE_ON / _MCLRE_OFF : GP3/MCLR pin function select
// _PWRTE_OFF / _PWRTE_ON : Power-up Timer Enable
// _WDT_ON / _WDT_OFF : WatchDogタイマ設定
// _LP_OSC / _XT_OSC / _HS_OSC / _EC_OSC : 200kHz以下外部/4MHz以下外部/4MHz以上外部/内部RC
// _INTRC_OSC_NOCLKOUT / _INTRC_OSC_CLKOUT : INTOSC oscillator: CLKOUT function
// _EXTRC_OSC_NOCLKOUT / _EXTRC_OSC_CLKOUT : EC: I/O function
//--------------------------------------------------------------------
int at 0x2007 __config = _CP_OFF & _CPD_OFF & _BODEN_OFF & _MCLRE_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT;
void Delay(volatile long dly)
{
while(dly-- > 0x00) {;}
}
//----------------------------------------------------------------------------
// 初期化
//----------------------------------------------------------------------------
void Init() {
CMCON = 0x07; // コンパレータ未使用
ANSEL = 0x11; // 8Tosc,AN0
ADCON0 = 0x01; // Left justified, Vref=Vdd,AN0,A/D_ON
TRISIO = 0x0F; // GP0~3:Input ,GP4~5:Output
WPU = 0x06; // GP1~2:キー入力端子はプルアップ抵抗
GPIO = 0x00;
//OPTION_REG = 0x81; // プリスケーラ: TMR0/4 0.256*4msec
OPTION_REG = 0x03; // プルアップ許可、プリスケーラ:TMR0/16(0.256*16msec)
TMR0 = 0x00;
T0IE = 1; // TMR0割り込み許可
}
//----------------------------------------------------------------------------
// ボリューム電圧値
//----------------------------------------------------------------------------
unsigned char volume() {
unsigned char tmp;
if (GO_DONE == 0) { // 変換済み?
tmp = ADRESH; // 上位8bit (前回の変換結果!)
GO_DONE = 1; // A/D変換開始
//while ( GO_DONE ){;} // 変換待ち
return tmp;
}
else
return 0x00;
}
//----------------------------------------------------------------------------
// LEDを点灯する処理
//----------------------------------------------------------------------------
void LED_ON() {
GPIO &= ~0x20;
}
//----------------------------------------------------------------------------
// LEDを消灯する処理
//----------------------------------------------------------------------------
void LED_OFF() {
GPIO |= 0x20;
}
//----------------------------------------------------------------------------
// Buzzer On する処理
//----------------------------------------------------------------------------
void BUZZER_ON() {
GPIO |= 0x10;
}
//----------------------------------------------------------------------------
// Buzzer Off する処理
//----------------------------------------------------------------------------
void BUZZER_OFF() {
GPIO &= ~0x10;
}
//----------------------------------------------------------------------------
// Dotポートチェック
//----------------------------------------------------------------------------
char ChkDotPort() {
if ((GPIO & 0x02) == 0) return 1;
return 0;
}
//----------------------------------------------------------------------------
// Dashポートチェック
//----------------------------------------------------------------------------
char ChkDashPort() {
if ((GPIO & 0x04) == 0) return 1;
return 0;
}
//----------------------------------------------------------------------------
// Set Output port
//----------------------------------------------------------------------------
void SetOutput()
{
if ((ParaCode == PARA_DASH_ON) || (ParaCode == PARA_DOT_ON)) {
LED_ON();
BUZZER_ON();
}
else {
LED_OFF();
BUZZER_OFF();
}
}
//----------------------------------------------------------------------------
// Check Input port
//----------------------------------------------------------------------------
void ChkInputPort()
{
// for Dot
if (ParaCode != PARA_DOT_ON) {
if (CntDotOn < LIMIT_VALUE) {
if (ChkDotPort()) // Dotポートチェック
CntDotOn ++;
else
CntDotOn = 0;
}
}
// for Dash
if (ParaCode != PARA_DASH_ON) {
if (CntDashOn < LIMIT_VALUE) {
if (ChkDashPort()) // Dashポートチェック
CntDashOn ++;
else
CntDashOn = 0;
}
}
}
//----------------------------------------------------------------------------
// Set Parameter Dash
//----------------------------------------------------------------------------
char SetParaDash()
{
if (CntDashOn >= LIMIT_VALUE) {
CntDashOn = 0;
ParaCode = PARA_DASH_ON;
ParaTime = (ADCData * 3);
return 1;
}
return 0;
}
//----------------------------------------------------------------------------
// Set Parameter Dot
//----------------------------------------------------------------------------
char SetParaDot()
{
if (CntDotOn >= LIMIT_VALUE) {
CntDotOn = 0;
ParaCode = PARA_DOT_ON;
ParaTime = ADCData;
return 1;
}
return 0;
}
//----------------------------------------------------------------------------
// キー処理メイン関数
//----------------------------------------------------------------------------
void key_sequence(void)
{
unsigned char tmp;
Timer100ms ++;
if (Timer100ms > 25) {
Timer100ms = 0x00;
tmp = volume();
if (tmp > 0x00) {
tmp >>= 0x02;
ADCData = tmp;
ADCData += MAX_SPEED;
}
}
if (ParaTime != 0) {
ParaTime --;
if (ParaTime == 0) {
if (ParaCode == PARA_DOT_ON) {
ParaCode = PARA_DOT_OFF;
ParaTime = ADCData;
}
else if (ParaCode == PARA_DASH_ON) {
ParaCode = PARA_DASH_OFF;
ParaTime = ADCData;
}
else if (ParaCode == PARA_DOT_OFF) {
if (!SetParaDash())
ParaCode = PARA_ALL_OFF;
}
else if (ParaCode == PARA_DASH_OFF) {
if (!SetParaDot())
ParaCode = PARA_ALL_OFF;
}
else {
ParaCode = PARA_ALL_OFF;
}
SetOutput();
}
}
ChkInputPort();
if (ParaCode == PARA_ALL_OFF) {
if (!SetParaDot())
SetParaDash();
}
SetOutput();
}
//----------------------------------------------------------------------------
// 割り込み(タイマ割り込みのみ使用)
//----------------------------------------------------------------------------
static void Inntrpt(void) interrupt 0
{
if (T0IF) { // TMR0割り込み?
T0IF = 0; // 割り込みフラグクリア
key_sequence(); // キー処理メイン関数
}
}
//----------------------------------------------------------------------------
// Main関数
//----------------------------------------------------------------------------
main()
{
Init(); // システムレジスタ初期化
// ユーザメモリの初期化
CntDashOn = 0;
CntDotOn = 0;
ADCData = MAX_SPEED;
ParaTime = 0;
ParaCode = PARA_ALL_OFF;
LED_OFF();
BUZZER_OFF();
GIE = 1; // 全割り込み許可
while (1) {
;
}
}
不明点やご質問はお気軽に、コメント欄、またはお問合せフォームにてご連絡ください。
スクイズ機能で不用意にキーがメモリされてしまい、速度を上げると余計な符号が出る不具合があります。
この記事へのコメント
お忙しい中、突然のメール失礼します。
[PIC12F675でエレキー] について困っています。
SDCC でコンパイルできません。Win7 or XP 互換モードで行いましたがエラーが出ます。
error 20; Undefined ifentifier 'CMCON'
ANSEL
ADCOND
~
GPIO
よろしくお願いします。
なおエレキーが動きましたら、貴殿のページにリンク張らせてもらっても、宜しいでしょうか?
[PIC12F675でエレキー] について困っています。
SDCC でコンパイルできません。Win7 or XP 互換モードで行いましたがエラーが出ます。
error 20; Undefined ifentifier 'CMCON'
ANSEL
ADCOND
~
GPIO
よろしくお願いします。
なおエレキーが動きましたら、貴殿のページにリンク張らせてもらっても、宜しいでしょうか?
Posted by JR6AUA at 2011年06月02日 12:17
GA JR6AUA OM
調べたところ、現在のSDCC・PICライブラリのライセンスが変更になって、ヘッダファイルのインストール先が以前と異なるようです。
エラーをなくすためには、
C:\Program Files\SDCC\non-free\include\
内のフォルダとファイルをまとめて
↓
C:\Program Files\SDCC\include\ へコピー
C:\Program Files\SDCC\non-free\lib\
内のフォルダとファイルをまとめて
↓
C:\Program Files\SDCC\lib\ へコピー
かつ、
at と記述している箇所を __at にする。
interrupt と記述している箇所を __interrupt にする。
以上でHEXファイルが生成されると思います。
調べたところ、現在のSDCC・PICライブラリのライセンスが変更になって、ヘッダファイルのインストール先が以前と異なるようです。
エラーをなくすためには、
C:\Program Files\SDCC\non-free\include\
内のフォルダとファイルをまとめて
↓
C:\Program Files\SDCC\include\ へコピー
C:\Program Files\SDCC\non-free\lib\
内のフォルダとファイルをまとめて
↓
C:\Program Files\SDCC\lib\ へコピー
かつ、
at と記述している箇所を __at にする。
interrupt と記述している箇所を __interrupt にする。
以上でHEXファイルが生成されると思います。
Posted by 宇都宮 at 2011年06月02日 14:21
JR6AUA OM
リンクの件は全く問題ありません。
なるべく多くリンクを張って頂ければ幸いです。
では。
リンクの件は全く問題ありません。
なるべく多くリンクを張って頂ければ幸いです。
では。
Posted by 宇都宮 at 2011年06月02日 17:24
早速の、ご回答ありがとうございます。
やってみました結果 .hex までは行きませんでしたが .asm が作れましたので書込みはできました。
これでやってみます。ありがとうございました。
やってみました結果 .hex までは行きませんでしたが .asm が作れましたので書込みはできました。
これでやってみます。ありがとうございました。
Posted by JR6AUA at 2011年06月02日 20:21
この .asm ファイルでは動作しませんでした。
色々やってみて、program files (x86) にしてなかったり・・・
結局 .hex ファイルの作成に成功しました。
やっと動作しました。ありがとうございます。
感謝いたします。
色々やってみて、program files (x86) にしてなかったり・・・
結局 .hex ファイルの作成に成功しました。
やっと動作しました。ありがとうございます。
感謝いたします。
Posted by JR6AUA at 2011年06月02日 23:34
無事に動作したようで安心しました。
Posted by 宇都宮 at 2011年06月03日 09:57
SDCCの環境でコンパイル(HEX作成)可能です。とありますが、SDCC4.1.0X64をインストールしようと起動するとWindowsによって浜っ子保護されます。これは無視していいものでしょうか?
又、他の使用可能な環境があればお教えください。
横浜市 中川
又、他の使用可能な環境があればお教えください。
横浜市 中川
Posted by JA5ZZ/1 at 2021年04月07日 15:10
> SDCC4.1.0X64をインストールしようと起動するとWindowsによって浜っ子保護されます。これは無視していいものでしょうか?
すみません。最近SDCCは使っていないのでコメントできません。
>他の使用可能な環境があればお教えください。
現在であれば、MicrochipのMPLAB X IDE + Cコンパイラ で良いかと思います。
ヘッダファイルの入替と
レジスタ名でエラーになるかと思いますので、若干の変更が必要になると思います。
すみません。最近SDCCは使っていないのでコメントできません。
>他の使用可能な環境があればお教えください。
現在であれば、MicrochipのMPLAB X IDE + Cコンパイラ で良いかと思います。
ヘッダファイルの入替と
レジスタ名でエラーになるかと思いますので、若干の変更が必要になると思います。
Posted by 宇都宮 at 2021年04月07日 15:33