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