· 

今さらPIC(ペリフェラルSPI)

PIC12F1840のMSSPを使ってSPIを撃ってみます。MCC使うと簡単という噂ですが、なぜかうまくいかなかったので、自力で行きます。

で、めんどくさいので、いきなり最終コードです。今回はLVP=OFFです。なんか、MCLRピンを専用で確保できるならHVのほうが良いということがどこかに書いてあったので。

MCCでうまくいかなかったのですが、MCCで生成したコードを参考にして作成しました。くだらないところで結構悩みましたが、、、MCCと違って、ペリフェラルの割り込みでバッファを更新するようにしたので、SPI送信中に別のことができます。

  1. /*
  2.  * File:   main.c
  3.  * Author: 
  4.  *
  5.  * Created on November 3, 2020, 6:27 PM
  6.  */
  7. // PIC12F1840 Configuration Bit Settings
  8. // 'C' source line config statements
  9. // CONFIG1
  10. #pragma config FOSC = INTOSC    // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
  11. #pragma config WDTE = OFF       // Watchdog Timer Enable (WDT disabled)
  12. #pragma config PWRTE = OFF      // Power-up Timer Enable (PWRT disabled)
  13. #pragma config MCLRE = ON       // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
  14. #pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
  15. #pragma config CPD = OFF        // Data Memory Code Protection (Data memory code protection is disabled)
  16. #pragma config BOREN = OFF      // Brown-out Reset Enable (Brown-out Reset disabled)
  17. #pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
  18. #pragma config IESO = OFF       // Internal/External Switchover (Internal/External Switchover mode is disabled)
  19. #pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is disabled)
  20. // CONFIG2
  21. #pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
  22. #pragma config PLLEN = OFF      // PLL Enable (4x PLL disabled)
  23. #pragma config STVREN = OFF     // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will not cause a Reset)
  24. #pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
  25. #pragma config LVP = OFF         // Low-Voltage Programming Enable (Low-voltage programming enabled)
  26. // #pragma config statements should precede project file includes.
  27. // Use project enums instead of #define for ON and OFF.
  28. #include <stdint.h>
  29. #include <xc.h>
  30. #define _XTAL_FREQ 8000000
  31. typedef struct {
  32.     uint8_t len;
  33.     uint8_t pos;
  34.     uint8_t ongoing;
  35.     uint8_t txbuf[16];
  36.     uint8_t rxbuf[16];
  37. }spi_tx_buf_t;
  38. volatile spi_tx_buf_t stbuf;
  39. void __interrupt() isr(void){
  40.     if(PIR1&0x08){
  41.         PIR1&=~0x08;
  42.         stbuf.rxbuf[stbuf.pos]=SSP1BUF;
  43.         stbuf.pos=stbuf.pos+1;
  44.         if(stbuf.pos<stbuf.len){
  45.             SSP1BUF=stbuf.txbuf[stbuf.pos];
  46.         }else{
  47.             stbuf.ongoing=0;
  48.         }
  49.     }
  50. }
  51. void SPI_master_begin(){
  52.     unsigned char dummy;
  53.     SSPSTAT&=  ~(0b01000000);
  54.     SSP1CON1=   (0b00001010);
  55.     SSP1CON2=   (0b00000000);
  56.     SSP1CON3=   (0b00000000);
  57.     SSP1ADD =   (0b00000001);
  58.     PIE1   |=   (0b00001000);
  59.     INTCON |=   (0b11000000);
  60.     dummy=SSP1BUF;
  61.     SSP1CON1|=  (0b00100000);
  62. }
  63. void SPI_master_end(){
  64.     SSP1CON1&= ~(0b00100000);
  65. }
  66. void SPI_ExchangeBlock(uint8_t* data,uint8_t len){
  67.     uint8_t i;
  68.     for(i=0;i<len;i++){
  69.         stbuf.txbuf[i]=data[i];
  70.         stbuf.rxbuf[i]=0;
  71.     }
  72.     stbuf.len=len;
  73.     stbuf.pos=0;
  74.     stbuf.ongoing=1;
  75.     SSP1BUF=stbuf.txbuf[stbuf.pos];
  76. }
  77. void setup(void){
  78.     OSCCON =  (0b01110000);// 8MHz
  79.     WPUA =     (0b00000000);
  80.     OPTION_REG=(0b00011111);
  81.     APFCON =   (0b01100000);// set RA4 as SDO, RA0 as nSS
  82.     
  83.     ANSELA =   (0b00000000);// set all pin as digital
  84.     TRISA &=  ~(0b00010010);// set RA4,1 as output
  85.     PORTA &=  ~(0b00010010);// output Low on RA4,1
  86.     
  87.     SPI_master_begin();
  88. }
  89. #define MULTI_BYTE
  90. void loop(void){
  91. #ifdef MULTI_BYTE
  92.     uint8_t data[]={0x00,0x01,0x02,0x03,0x04,0x05,0x11,0x22,0xAA};
  93.     SPI_ExchangeBlock(data,9);
  94.     __delay_ms(200);
  95. #else
  96.     uint8_t i;
  97.     for(i=0;i<255;i++){
  98.         if(stbuf.ongoing==0){
  99.             SPI_ExchangeBlock(&i,1);
  100.             __delay_ms(200);
  101.         }
  102.     }
  103. #endif
  104. }
  105. void main(void) {
  106.     setup();
  107.     while(1){
  108.         loop();
  109.     }
  110.     return;
  111. }

 

MULTI_BYTEでやってみた。よさそう。

1バイトずつやってみた。よさそう。