2016年8月31日水曜日

ラズペリーパイで自力シリアル通信

ひょんなことから、過去にFONのGPIOを使ったなんちゃってシリアル通信を実装したのを思い出した。過去の投稿
 当時は、ラズベリーパイが注目されていて、いいな−と思いつつ、ちょっと高いなと感じており、中古で@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
#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;
}
view raw myi2c_test.c hosted with ❤ by GitHub
PIC側
RB0 - CLK IN (割り込み)
RB5 - DATA IN
RB2 - TX
/*
* 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;
}
view raw main.c hosted with ❤ by GitHub
なんとなく達成感があるね。
次はPICからラズピ側に送信する機能を作ってみよう。

2016年8月22日月曜日

2つ同時に初期不良品をつかんでしまった

こんなこともあるのかと・・・。

Amazonで購入した3TBの外付けHDDと近所のハードオフで購入した光BOX3が見事に初期不良品だった。

・HDD MAL33000EX3 3TB @9,890

安さに惹かれてついつい買ってしまい、レビューを見て愕然。
リフレッシュ品とか初期不良の文字が目立つ。
実際HDDとして認識しないし、フォーマットかけてもエラーになるし・・・。

・光BOX3 @1,500
HDMI出力されない。TVにつないでもパソコンモニターにつないでもだめ。


まぁついていないことは重なるものだね。。。
返品できるかなぁ。Orz