当時は、ラズベリーパイが注目されていて、いいな−と思いつつ、ちょっと高いなと感じており、中古で@500円程度で入手できるFONを何とか拡張できなかと思っていた。
結局受信エラーが抑えきれなくて、途中興味を失ってしまった。
最近になって、
1.2014年7月 トランジスタ技術
2.LINUXデバイスドライバ
3.RaspberryPiで学ぶARMデバイスドライバープログラミング
を読む機会があって、FONでやりたかったことを再度挑戦してみようと思った。
そのまえに、情報が豊富なラズベリーパイで準備運動をしてみた記録。
概要
ユーザーランドでGPIOをパタパタさせて、同期型シリアル通信を行い、
PICマイコンにて、UARTに変換する。
ラズピでuname -aを実行してPIC経由のURATで受信した結果。
ラズピ側
ユーザーランドでGPIOをパタパタさせるプログラム
ほとんど前述の 「3」のとおり
GPIO7 - CLK OUT
GPIO8 - DATA OUT
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <unistd.h> | |
#include <rpi_gpio.h> | |
#include <rpi_gpiolib.h> | |
#define LED_BASE 7 | |
void led_init(void) | |
{ | |
// GPIOファンクションセット | |
rpi_gpio_function_set( LED_BASE+0, RPI_GPF_OUTPUT );//CLK | |
rpi_gpio_function_set( LED_BASE+1, RPI_GPF_OUTPUT );//DATA | |
rpi_gpio_function_set( LED_BASE+2, RPI_GPF_OUTPUT ); | |
rpi_gpio_function_set( LED_BASE+3, RPI_GPF_OUTPUT ); | |
} | |
void gpio_put_lsb(unsigned char v ) | |
{ | |
// 4ビットクリア | |
//rpi_gpio_clear32( RPI_GPIO_P1MASK, (3 & 0x0F) << LED_BASE); | |
printf("0b"); | |
volatile int i=0; | |
for(i=0;i<8;i++){ | |
//CLK=L | |
rpi_gpio_clear32( RPI_GPIO_P1MASK, (1 & 0x0F) << LED_BASE); | |
usleep(100); | |
//DATA | |
//printf("i=%d,v=%#x,v2=%d\n",i,v,v%2); | |
printf("%d",v%2); | |
if(v % 2 == 1){ | |
rpi_gpio_set32( RPI_GPIO_P1MASK, (2 & 0x0F) << LED_BASE); | |
}else{ | |
rpi_gpio_clear32( RPI_GPIO_P1MASK, (2 & 0x0F) << LED_BASE); | |
} | |
usleep(100); | |
//CLK=H | |
rpi_gpio_set32( RPI_GPIO_P1MASK, (1 & 0x0F) << LED_BASE); | |
usleep(100); | |
v=v>>1; | |
} | |
printf("\n"); | |
} | |
void gpio_put_msb(unsigned char v ) | |
{ | |
// 4ビットクリア | |
//rpi_gpio_clear32( RPI_GPIO_P1MASK, (3 & 0x0F) << LED_BASE); | |
printf("0b"); | |
volatile int i=0; | |
for(i=0;i<8;i++){ | |
//CLK=L | |
rpi_gpio_clear32( RPI_GPIO_P1MASK, (1 & 0x0F) << LED_BASE); | |
usleep(100); | |
//DATA | |
//printf("i=%d,v=%#x,v2=%d\n",i,v,((v & 0x80) == 0x80 ? 1 : 0)); | |
printf("%d",((v & 0x80) == 0x80 ? 1 : 0)); | |
if((v & 0x80) == 0x80){ | |
rpi_gpio_set32( RPI_GPIO_P1MASK, (2 & 0x0F) << LED_BASE); | |
}else{ | |
rpi_gpio_clear32( RPI_GPIO_P1MASK, (2 & 0x0F) << LED_BASE); | |
} | |
usleep(100); | |
//CLK=H | |
rpi_gpio_set32( RPI_GPIO_P1MASK, (1 & 0x0F) << LED_BASE); | |
usleep(100); | |
v=v<<1; | |
} | |
printf("\n"); | |
} | |
int main(int argc,char *argv[]) | |
{ | |
// GPIO初期化 | |
if( ! rpi_gpio_init() ) | |
return -1; | |
led_init(); | |
int c=0; | |
if(argc==2){ | |
while(argv[1][c]){ | |
//ASCII値として送信する | |
printf("Char = %c(%#x) ",argv[1] [c],argv[1] [c]); | |
gpio_put_msb(argv[1] [c]); | |
c++; | |
} | |
}else if(argc==3){ //s | |
char buf[512]; | |
fgets(buf, sizeof(buf), stdin); | |
while(buf[c]){ | |
//ASCII値として送信する | |
printf("Char = %c(%#x) ",buf[c],buf[c]); | |
gpio_put_msb(buf[c]); | |
c++; | |
} | |
}else{ | |
unsigned int value = 0; | |
for( value = 0; value < 10; value++ ) { | |
printf("LED = %d\n", value ); | |
gpio_put_lsb(value); | |
sleep(1); | |
} | |
} | |
// mmap開放 | |
rpi_gpio_deinit(); | |
return 1; | |
} |
RB0 - CLK IN (割り込み)
RB5 - DATA IN
RB2 - TX
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* File: main.c | |
* Author: adeno | |
* | |
* Created on 2016/08/31, 9:58 | |
*/ | |
#include <xc.h> | |
// CONFIG | |
#pragma config FOSC = INTOSCIO // Oscillator Selection bits (INTOSC oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN) | |
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled) | |
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled) | |
#pragma config MCLRE = ON // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is MCLR) | |
#pragma config BOREN = ON // Brown-out Detect Enable bit (BOD enabled) | |
#pragma config LVP = ON // Low-Voltage Programming Enable bit (RB4/PGM pin has PGM function, low-voltage programming enabled) | |
#pragma config CPD = OFF // Data EE Memory Code Protection bit (Data memory code protection off) | |
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off) | |
#define _XTAL_FREQ 4000000 // delay_ms(x) のための定義 | |
unsigned char rbuf=0,rcnt=0; | |
void putsUSART(char *str){ | |
while(*str){ | |
while (!TXIF); | |
TXREG = *str++; | |
} | |
} | |
void putc(unsigned char c){ | |
while(!TXIF){ | |
} | |
TXREG = c; | |
} | |
static void interrupt intr(void) { | |
if(INTF){ //INT割り込み | |
INTE = 0; //INT割り込み禁止 | |
INTF = 0; | |
if(RB5 ==1){ | |
rbuf = (rbuf<<1) + 0x01; | |
}else{ | |
rbuf = (rbuf<<1) + 0x00; | |
} | |
rcnt++; | |
if(rcnt >= 8){ | |
rcnt=0; | |
putc(rbuf); | |
} | |
INTE = 1; //INT割り込み開始 | |
} | |
} | |
void main(void) { | |
OSCF = 1; //4MHz | |
PORTA = 0b00000000; //PORTAの中身をきれいにする | |
TRISA = 0b00000000; //PORTAは 1:入力 0:出力 | |
PORTB = 0b00000000; //PORTBの中身をきれいにする | |
TRISB = 0b00100111; //PORTBは 1:入力 0:出力 | |
PORTB = 0b00001000; | |
//USARTの初期化 | |
TXSTA = 0b00100100; | |
RCSTA = 0b10010000; | |
SPBRG = 25; //ボーレート9600dpb @4MHz | |
//割り込みの設定 | |
INTEDG = 1; //RB0 立ち上がり | |
INTF = 0; // RB0/INT外部割込みフラグをクリア | |
INTE = 1; // RB0/INT外部割込み許可 | |
GIE = 1; // すべての割り込み許可 | |
//SFR-RXの初期化 | |
rbuf = 0; | |
rcnt = 0; | |
unsigned char wtim=0; | |
__delay_ms(100); // 100ms | |
putsUSART("Hello OK>\r\n"); | |
while(1){ | |
PORTB = 0b00001000; | |
__delay_ms(100); // 100ms | |
//putsUSART("Hello OK>\r\n"); | |
PORTB = 0b00000000; | |
__delay_ms(100); // 100ms | |
if(rcnt>0){ | |
wtim++; | |
if(wtim==10){ | |
rcnt=0; | |
wtim=0; | |
putsUSART("Timeout\r\n"); | |
} | |
} | |
} | |
return; | |
} |
次はPICからラズピ側に送信する機能を作ってみよう。