質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

マイコン

マイクロコンピュータの略で、CPUにマイクロプロセッサを用いたコンピュータのこと。家電製品、電磁機器などの制御に用いられています。単体でコンピュータとしての機能を一通り備えています。 現代のパーソナルコンピュータに近く、同時期のメインフレームやミニコンピュータと比べ、小さいことが特徴です。

Q&A

1回答

2298閲覧

C言語でのSPI通信のビット演算について

TatsuyaMorita

総合スコア55

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

マイコン

マイクロコンピュータの略で、CPUにマイクロプロセッサを用いたコンピュータのこと。家電製品、電磁機器などの制御に用いられています。単体でコンピュータとしての機能を一通り備えています。 現代のパーソナルコンピュータに近く、同時期のメインフレームやミニコンピュータと比べ、小さいことが特徴です。

0グッド

0クリップ

投稿2022/03/13 05:48

編集2022/03/13 06:06

https://www.denshi.club/parts/2021/04/raspberry-pi-pico-12-spi-apia-dmcp.html
を見て、下記のC言語プログラムをRaspberry Pi Picoに書き込んだら、MCP3008とSPI通信が出来たようなのですが、このプログラムは、GP5をLowにしてから、GP3から3バイト、ダミーデータをMCP3008に書きこんで、MCP3008からRaspberry Pi Picoに返ってきた値3バイトをbufferに格納して、2バイト目のbufferと8ビット符号なし00000011の論理積を8ビット左にシフトした値と3バイト目のbufferの論理和に3.2562をかけて1024で割るみたいなことをしているのですか?
例えば、2バイト目のbufferが00100010で3バイト目のbufferが00101100だったら、00100010と00000011の論理積で00000010となり、00000010を8ビット左にシフトすると、00000000となり、00000000と00101100の論理和が44となり、44*3.2562/1024で0.13991484375になるということですか?
また、SPIのボーレートが2MHzとなっているのは、サンプル期間が終了してから10データビットがすべてクロック出力されるまでの時間が1.2 msを超えてはならないとMCP3008の仕様書に書いてあるからでしょうか?SPIのボーレートは1kHz以上ならどんな値でも大丈夫でしょうか?

#include <stdio.h> #include "pico/stdlib.h" #include "hardware/spi.h" #include "hardware/gpio.h" #include "hardware/adc.h" #define PIN_SCK 2 #define PIN_MOSI 3 #define PIN_MISO 4 #define PIN_CS 5 #define SPI_PORT spi0 static float Vref = 3.2562; static inline void cs_select() { asm volatile("nop \n nop \n nop"); gpio_put(PIN_CS, 0); // Active low asm volatile("nop \n nop \n nop"); } static inline void cs_deselect() { asm volatile("nop \n nop \n nop"); gpio_put(PIN_CS, 1); asm volatile("nop \n nop \n nop"); } void setup_SPI(){ // This example will use SPI0 at 2MHz. spi_init(SPI_PORT, 2 * 1000 * 1000); gpio_set_function(PIN_MISO, GPIO_FUNC_SPI); gpio_set_function(PIN_SCK, GPIO_FUNC_SPI); gpio_set_function(PIN_MOSI, GPIO_FUNC_SPI); // Chip select is active-low, so we'll initialise it to a driven-high state gpio_init(PIN_CS); gpio_set_dir(PIN_CS, GPIO_OUT); gpio_put(PIN_CS, 1); } int readADC(uint8_t ch){ uint8_t writeData[] = {0b00000001, 0x00, 0x00}; switch(ch){ case 0: writeData[1] = 0b10000000; break; case 1: writeData[1] = 0b10010000; break; case 2: writeData[1] = 0b10100000; break; case 3: writeData[1] = 0b10110000; break; case 4: writeData[1] = 0b11000000; break; case 5: writeData[1] = 0b11010000; break; case 6: writeData[1] = 0b11100000; break; case 7: writeData[1] = 0b11110000; } // printf("\n %0b %0b %0b\n",writeData[0],writeData[1],writeData[2]); uint8_t buffer[3]; cs_select(); sleep_ms(1); spi_write_read_blocking(SPI_PORT, writeData, buffer, 3); sleep_ms(1); cs_deselect(); return (buffer[1] & 0b00000011) << 8 | buffer[2]; } int main() { stdio_init_all(); adc_init(); adc_gpio_init(26); adc_select_input(0); const float conversion_factor = Vref / (1 << 12); printf("\nHello, MCP3008 Reading raw data from registers via SPI...\n"); setup_SPI(); while (1) { for (uint8_t i=0; i<8; i++){ printf("ch%d is %.4fV\n", i, Vref * readADC(i) / 1024); sleep_ms(10); } uint16_t result = adc_read(); printf("ADC voltage: %f V\n", result * conversion_factor); sleep_ms(5000); } return 0; }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jimbe

2022/03/13 06:10

コードの動作は動かして変数を見れば分かることではないでしょうか。 また、仕様と照らし合わせられるのであれば書かれている通り(もしくは書かれて'いない'通り(?))なのだろうと思うのですが、何が問題なのでしょうか。
TatsuyaMorita

2022/03/13 06:16

回答ありがとうございます。どうして、return (buffer[1] & 0b00000011) << 8 | buffer[2];になるのかがよく分かりませんでした。
jimbe

2022/03/13 06:41 編集

> 00000010を8ビット左にシフトすると、00000000となり、 ここが違うと思います。 詳しい仕様は分かりませんが、恐らくお使いの C の int は 8 ビットでは無いのではないでしょうか。 元のサイズ(buffer[1])は 8 ビットでも、計算中は 16 ビットや 32 ビット等お使いの C の int のサイズに拡張されて表現されると思います。 従いまして 00000010を8ビット左にシフトすると、1000000000となり、 1000000000と00101100の論理和が556(1000101100)となり ます。 これも readADC の結果を表示するようにしてみれば確認出来るのではないでしょうか。
guest

回答1

0

MCP3008のデータシートを読みましょう。
そこに全て書いてあります

イメージ説明

ラズパイから3バイトを送信後、3バイトのデータを受信します
受信データは、最初のバイトはダミーデータで、2番めはA/D結果の上位2ビット、3番めは下位8ビットです

投稿2022/03/13 06:25

y_waiwai

総合スコア87784

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問