USB-UART通信   

 USB-シリアル変換モジュールのTXDとRXDを使ってTeraTerm経由で通信することが多くあります。ほとんどの場合は高速を必要としませんので19200bpsで通信しています。プログラムを書くための参考資料をここに置く予定です。


 1 基本プログラム1 tiny2313 mega328
 2 基本プログラム1 mega8 の場合
 3 ポーリングによる読み書き mega8,mega328




















 1 基本プログラム1 tiny2313 mega328(赤文字に注意)

Tiny2313の例です。ターゲットボードからメニューをTeraTermに送ります。
#include <avr/io.h>
#include <avr/interrupt.h>
#include <string.h>                  // string
#include <util/delay.h>
//#include <stdlib.h>                // itoa
#include <avr/pgmspace.h>

  volatile  uint8_t rflg;          // uart受信フラグ
  volatile  uint8_t rdat;            // 受信データ
  volatile  char recbuf[20];         // uart受信バッファ
  volatile  uint8_t rec_i=0;         // rec_index

  /* プロトタイプ宣言 */
  void string_out (char *msg_string);               // UART送信


/* 受信割込ルーチン   */
ISR(USART_RX_vect){                                       /* データを読み出すとクリアされる rdat:char変数 */
  recbuf[rec_i]=UDR;   // tn2313  
  recbuf[rec_i]=UDR0;  // m328  
  if((recbuf[rec_i]=='\0')||(recbuf[rec_i]==0x0d)||(recbuf[rec_i]==0x0a)){
    recbuf[rec_i]='\0';
    rflg=1;
    rec_i=0;
    cli();
  } else{                
    rec_i++;
  }
}

//----------------------------------------------------------------------------------------------------------
int main(void)      /* ***************************  main  ************************************************* */
{
  char s[20];
  char msg[30];
  uint8_t menu_n,i;

  /* USART設定  tiny2313 */
  UBRRH = 0;                                       /* 25MHz n=0 ボーレート設定  */
  UBRRL = F_CPU/16/19200-1;                        /* 25MHz n=0 ボーレート設定 19200bsp=80  F_CPU/16/BOUD-1 */
  UCSRB = 0b10011000;                              /* _BV(RXEN)|_BV(TXEN)|_BV(RXCIE);   送受信許可 受信割込許可  */
  UCSRC = 6;                                       /* フレーム形式設定(8ビット,1ストップビット) */

  /* USART設定  mega328 */
  UBRR0H = 0;                                       /* 25MHz n=0 ボーレート設定  */
  UBRR0L = F_CPU/16/19200-1;                        /* 25MHz n=0 ボーレート設定 19200bsp=80  F_CPU/16/BOUD-1 */
  UCSR0B = 0b10011000;                              /* _BV(RXEN)|_BV(TXEN)|_BV(RXCIE);   送受信許可 受信割込許可  */
  UCSR0C = 6;                                       /* フレーム形式設定(8ビット,1ストップビット) */



  sei();

//-------------------メニュー選択  menu_n値設定 --------------------------------------------------------
  strcpy_P(msg,PSTR(" ")); string_out(msg);
  strcpy_P(msg,PSTR("-- menu --")); string_out(msg);
  strcpy_P(msg,PSTR("メニュー1")); string_out(msg);
  strcpy_P(msg,PSTR("メニュー2")); string_out(msg);
  strcpy_P(msg,PSTR("  ")); string_out(msg);

  while(rflg==0){
    if(rflg==1){break;}
  }
  rflg=0;
  for(i=0;i<20;i++){s[i]=recbuf[i];}    //        strcpy(s,recbuf);  //
  menu_n=s[0]-0x30;

  start0: //ラベル メニューNから直接戻る時のジャンプラベル

  if(menu_n==1){                            //  メニュー1  1111111111111111111111
    strcpy_P(msg,PSTR("メッセージ送信 to PC 111 ")); string_out(msg);
    // メニュー 1 の処理---------
  }//11111111111111111111

  if(menu_n==2){                            //  メニュー2  222222222222222222222222222222222222 
    strcpy_P(msg,PSTR("メッセージ送信 to PC 222 ")); string_out(msg);
    // メニュー 2 の処理---------
  }//222222222222222222222

  while(1){
    // 最終処理
  }//while
}//------------メインルーチンの終わり------------------------------------------------------------


/* ----------------------  サブルーチン  ------------------------------------------------------ */
/* ************************ 文字列送信ルーチン tiny2313 ***************************************************** */
void string_out (char *msg_string){   /* "*"で受けると、呼び出し側の配列の番地を受け取る */ 
  uint8_t i;                   
  i=0;
  while (msg_string[i]  !='\0'){
    while ( !(UCSRA & _BV(UDRE)) );   //送信バッファの空きを待って
    UDR = msg_string[i];               //送信データをセット
    i++;
//    _delay_ms(1);
  }
  while(!(UCSRA & _BV(UDRE))); UDR = 0x0d; _delay_ms(6);    /* 送信バッファの空きを待ってデータをセット CRLF送信*/
  while(!(UCSRA & _BV(UDRE))); UDR = 0x0a; _delay_ms(6);    /* 送信バッファの空きを待ってデータをセット CRLF送信*/
}

/* ************************ 文字列送信ルーチン mega328 ***************************************************** */
void string_out (char *msg_string){   /* "*"で受けると、呼び出し側の配列の番地を受け取る */ 
  uint8_t i;                   
  i=0;
  while (msg_string[i]  !='\0'){
    while ( !(UCSR0A & _BV(UDRE0)) );   //送信バッファの空きを待って
    UDR0 = msg_string[i];               //送信データをセット
    i++;
//    _delay_ms(1);
  }
  while(!(UCSR0A & _BV(UDRE0))); UDR0 = 0x0d; _delay_ms(6);    /* 送信バッファの空きを待ってデータをセット CRLF送信*/
  while(!(UCSR0A & _BV(UDRE0))); UDR0 = 0x0a; _delay_ms(6);    /* 送信バッファの空きを待ってデータをセット CRLF送信*/
}

基本プログラム1 おわり 筆者メモ F:\prA\_2011\f_cntr_2313_spi_25mhz F:\prA\_2011\test33_25m_uart

 2 基本プログラム1 mega8 の場合 2019.11.29

 mega8は 328、168などと違って1世代前のチップのようです。そのために レジスタの名前が違い(0ゼロがない)、一部のレジスタの機能がちがいます。
上記と同じ機能のプログラムですがレジスタの違いのため単独で書きました。
/*************************************************************************************
   mega8 のUARTテスト    2019.11.29
   9600bpsでつなぎ、キー入力に従って文字列を返す。
   
   tiny2313、mega328などとは   UCSRC レジスタの機能が異なるので注意のこと。

*************************************************************************************/

#include <avr/io.h>
#include <avr/interrupt.h>
#include <string.h>                  // string
#include <util/delay.h>
//#include <stdlib.h>                // itoa
#include <avr/pgmspace.h>

volatile  uint8_t rflg;          // uart受信フラグ
volatile  uint8_t rdat;            // 受信データ
volatile  char recbuf[20];         // uart受信バッファ
volatile  uint8_t rec_i=0;         // rec_index

  /* プロトタイプ宣言 */
void string_out (char *msg_string);               // UART送信


/* 受信割込ルーチン   */
ISR(USART_RXC_vect) {                                     /* データを読み出すとクリアされる rdat:char変数 */
  recbuf[rec_i] = UDR;                                    /* m328の時は UDR0 */
  if ((recbuf[rec_i] == '\0') || (recbuf[rec_i] == 0x0d) || (recbuf[rec_i] == 0x0a)) {
    recbuf[rec_i] = '\0';
    rflg = 1;
    rec_i = 0;
    cli();
  } else {
    rec_i++;
  }
}

//----------------------------------------------------------------------------------------------------------
int main(void)      /* ***************************  main  ************************************************* */
{
  char s[20];
  char msg[30];
  uint8_t menu_n,i;

  /* USART設定  mega8 */
  UBRRH = 0;                                // 8MHz U2X=0 ボーレート設定  
  UBRRL = F_CPU / 16 / 9600 - 1;            // 8MHz U2X=0 ボーレート設定 9600bsp=51  F_CPU/16/BOUD-1 
  UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE);   // 0b10011000;_BV(RXEN)|_BV(TXEN)|_BV(RXCIE);   送受信許可 受信割込許可
  UCSRC = (1<<URSEL)|(0<<USBS)|(3<<UCSZ0);  // 142; フレーム形式設定(8ビット,1ストップビット,ノンパリティ) *328と機能違い注意
  UCSRA = 1;                                // U2X=0

  sei();

//-------------------メニュー選択  menu_n値設定 --------------------------------------------------------
  strcpy_P(msg,PSTR(" ")); string_out(msg);
  strcpy_P(msg,PSTR("-- menu --")); string_out(msg);
  strcpy_P(msg,PSTR("メニュー1")); string_out(msg);
  strcpy_P(msg,PSTR("メニュー2")); string_out(msg);
  strcpy_P(msg,PSTR("  ")); string_out(msg);

  while(rflg==0){
    if(rflg==1){break;}
  }
  rflg=0;
  for(i=0;i<20;i++){s[i]=recbuf[i];}    //        strcpy(s,recbuf);  //
  menu_n=s[0]-0x30;

  if(menu_n==1){                            //  メニュー1  1111111111111111111111
    strcpy_P(msg,PSTR("メッセージ送信 to PC 111 ")); string_out(msg);
    // メニュー 1 の処理---------
  }//11111111111111111111

  if(menu_n==2){                            //  メニュー2  222222222222222222222222222222222222 
    strcpy_P(msg,PSTR("メッセージ送信 to PC 222 ")); string_out(msg);
    // メニュー 2 の処理---------
  }//222222222222222222222

  while(1){
    // 最終処理
  }//while
}//------------メインルーチンの終わり------------------------------------------------------------


/* ----------------------  サブルーチン  ------------------------------------------------------ */
/* ************************ 文字列送信ルーチン tiny2313 ***************************************************** */
void string_out (char *msg_string) {  /* "*"で受けると、呼び出し側の配列の番地を受け取る */
  uint8_t i;
  i = 0;
  while (msg_string[i]  != '\0') {
    while ( !(UCSRA & (1 << UDRE)) ); //送信バッファの空きを待って
    UDR = msg_string[i];               //送信データをセット
    i++;
//    _delay_ms(1);
  }
  while ( !(UCSRA & (1 << UDRE)) ); UDR = 0x0d; //_delay_ms(6);    /* 送信バッファの空きを待ってデータをセット CRLF送信*/
  while ( !(UCSRA & (1 << UDRE)) ); UDR = 0x0a; //_delay_ms(6);    /* 送信バッファの空きを待ってデータをセット CRLF送信*/
  		//while(!(UCSRA & _BV(UDRE))); UDR = 0x0d;   /* 送信バッファの空きを待ってデータをセット CRLF送信*/
  		//while(!(UCSRA & _BV(UDRE))); UDR = 0x0a;   /* 送信バッファの空きを待ってデータをセット CRLF送信*/
}
筆者メモ \AVR\prA\m8\m8_uart_test1

ポーリングによる方法: 割り込みを使わず、読み取りに行きます。簡単なメニューではこちらのほうが便利でしょう。
/*************************************************************************************
   mega8 のUARTテスト    2019.11.29
   9600bpsでつなぎ、キー入力に従って文字列を返す。
   pollinによる。割り込みではない。

   tiny2313、mega328などとは   UCSRC レジスタの機能が異なるので注意のこと。

*************************************************************************************/

#include <avr/io.h>
#include <avr/interrupt.h>
#include <string.h>                  // string
#include <util/delay.h>
//#include <stdlib.h>                // itoa
#include <avr/pgmspace.h>

volatile  uint8_t rflg;          // uart受信フラグ
volatile  uint8_t rdat;            // 受信データ
volatile  char recbuf[20];         // uart受信バッファ
volatile  uint8_t rec_i = 0;       // rec_index

/* プロトタイプ宣言 */
void string_out (char *msg_string);               // UART送信

//----------------------------------------------------------------------------------------------------------
int main(void)      /* ***************************  main  ************************************************* */
{
  char s[20];
  char msg[30];
  uint8_t menu_n, i;

  /* USART設定  mega8 */
  UBRRH = 0;                                // 8MHz U2X=0 ボーレート設定
  UBRRL = F_CPU / 16 / 9600 - 1;            // 8MHz U2X=0 ボーレート設定 9600bsp=51  F_CPU/16/BOUD-1
  UCSRB = (1 << RXEN) | (1 << TXEN); // 0b10011000;_BV(RXEN)|_BV(TXEN)|_BV(RXCIE);   送受信許可 受信割込不可
  UCSRC = (1 << URSEL) | (0 << USBS) | (3 << UCSZ0); // 142; フレーム形式設定(8ビット,1ストップビット,ノンパリティ) *328と機能違い注意
  UCSRA = 1;                                // U2X=0

  //-------------------メニュー選択  menu_n値設定 --------------------------------------------------------
  strcpy_P(msg, PSTR(" ")); string_out(msg);
  strcpy_P(msg, PSTR("-- menu --")); string_out(msg);
  strcpy_P(msg, PSTR("メニュー1")); string_out(msg);
  strcpy_P(msg, PSTR("メニュー2")); string_out(msg);
  strcpy_P(msg, PSTR("  ")); string_out(msg);

  i = 0;
  while (1) {
    while ((UCSRA & _BV(RXC)) == 0);
    s[i] = UDR;
    if ((s[i] == 0x00) || (s[i] == 0x0d) || (s[i] == 0x0a)) {
      s[i] = 0x00;
      break;
    }
    i++;
  }

  menu_n = s[0] - 0x30;
  if (menu_n == 1) {                        //  メニュー1  1111111111111111111111
    strcpy_P(msg, PSTR("メッセージ送信 to PC 111 ")); string_out(msg);
    // メニュー 1 の処理---------
  }//11111111111111111111

  if (menu_n == 2) {                        //  メニュー2  222222222222222222222222222222222222
    strcpy_P(msg, PSTR("メッセージ送信 to PC 222 ")); string_out(msg);
    // メニュー 2 の処理---------
  }//222222222222222222222

  while (1) {
    // 最終処理
  }//while
}//------------メインルーチンの終わり------------------------------------------------------------


/* ----------------------  サブルーチン  ------------------------------------------------------ */
/* ************************ 文字列送信ルーチン tiny2313 ***************************************************** */
void string_out (char *msg_string) {  /* "*"で受けると、呼び出し側の配列の番地を受け取る */
  uint8_t i;
  i = 0;
  while (msg_string[i]  != '\0') {
    while ( !(UCSRA & (1 << UDRE)) ); //送信バッファの空きを待って
    UDR = msg_string[i];               //送信データをセット
    i++;
    //    _delay_ms(1);
  }
  while ( !(UCSRA & (1 << UDRE)) ); UDR = 0x0d; //_delay_ms(6);    /* 送信バッファの空きを待ってデータをセット CRLF送信*/
  while ( !(UCSRA & (1 << UDRE)) ); UDR = 0x0a; //_delay_ms(6);    /* 送信バッファの空きを待ってデータをセット CRLF送信*/
  //while(!(UCSRA & _BV(UDRE))); UDR = 0x0d;   /* 送信バッファの空きを待ってデータをセット CRLF送信*/
  //while(!(UCSRA & _BV(UDRE))); UDR = 0x0a;   /* 送信バッファの空きを待ってデータをセット CRLF送信*/
}
筆者メモ \AVR\prA\m8\m8_uart_test2_polling

  
2 基本プログラム1 mega8 の場合 おわり


 3 ポーリングによる読み書き  mega8,mega328

 サブルーチン部のみ取り出しました。
Cファイルはここです。 筆者メモ        
3 ポーリングによる読み書き おわり






















工事中  1 基本プログラム1 



基本プログラム1 おわり 筆者メモ F:\prA\_2011\f_cntr_2313_spi_25mhz F:\prA\_2011\test33_25m_uart











  

inserted by FC2 system