1. ハードウェア構成と接続概要
本デバイス(型番:XJ3100)は、標準的な SPI インターフェイスを介してシリアル通信データを転送する UART デバイスとして機能します。主に STM32 マイコンの GPIO を用いて外部デバイスを制御する際に使用されます。
開発環境には以下の主要コンポーネントが要求されます:
- マイコンユニット:STM32F407(または同等の ARM Cortex-M コア)
- 変換 IC:XJ3100(MAX3100 とピン互換)
- 水晶発振器:3.6864MHz(推奨)
物理インタフェース定義
XJ3100 とマイコン間のデータ転送経路は以下の通り定義されます:
| 信号名 | 色識別 | 機能用 | 接続先 |
|---|---|---|---|
| TX | 黄色 | UART 送信 | 相手機器 RX |
| MOSI | 薄青 | メインデバイスからの命令出力 | マイコン MOSI |
| CLK | 赤 | クロックパルス | マイコン SCK |
| CS | 濃紺 | チップセレクト(アクティブロー) | マイコン GPIO |
2. レジスタアーキテクチャ解説
XJ3100 の内部状態管理は、主に「設定レジスタ(Configuration)」と「データレジスタ(Data)」の 2 つの領域で構成されています。
データの書き込み・読み出しコマンドは、SPI 転送を行う際の MSB ビットによって判別されます。
- 設定レジスタ操作: クロック動作モードや停止位、パーリティ設定などを変更するためにアクセスされます。
- データレジスタ操作: 実際の UART データのバッファリングを行います。
3. ソフトウェア実装
以下に、C 言語を用いたドライバの実装例を示します。元のロジック構造を維持しつつ、可読性の高い関数名および変数名へ変更しています。
ヘッダファイル定義(xj3100_drv.h)
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html><html><body><pre><code>
#ifndef XJ3100_DRV_H_
#define XJ3100_DRV_H_
#include "stdint.h"
/* コマンドコード定義 */
#define OP_CODE_CONFIG_WR (0xC0)
#define OP_CODE_CONFIG_RD (0x40)
#define OP_CODE_DATA_WR (0x80)
#define OP_CODE_DATA_RD (0x00)
/* ビットフラグ定義(設定レジスタ用) */
#define MASK_R_FLAG (0x8000)
#define MASK_T_FLAG (0x4000)
#define MASK_FEN_EN (0x2000) /* FIFO Enable */
#define MASK_SHDN_MODE (0x1000)
#define MASK_TM_INT (0x0800)
#define MASK_RM_INT (0x0400)
#define MASK_PM_INT (0x0200)
#define MASK_RAM_INT (0x0100)
#define MASK_IR_MODE (0x0080) /* IRDA Mode */
#define MASK_STP_POS (0x0040) /* Stop Bit Pos */
#define MASK_PE_EN (0x0020) /* Parity Enable */
#define MASK_LEN_BIT (0x0010) /* Length Bit */
#define MASK_BAUD_MASK (0x000F) /* Baudrate Select */
/* ビットフラグ定義(データレジスタ用) */
#define MASK_ERROR_RA_FE (0x0400) /* Receive Active / Frame Error */
#define MASK_CTS_STATE (0x0200)
#define MASK_PR_BIT (0x0100) /* Parity Result */
/* 設定値定数 */
typedef enum {
BAUD_RATE_600 = 0x0F,
BAUD_RATE_1200,
BAUD_RATE_2400,
BAUD_RATE_4800,
BAUD_RATE_9600,
BAUD_RATE_19200,
BAUD_RATE_38400,
BAUD_RATE_76800,
BAUD_RATE_115200,
/* ...その他のボーレート定義は省略*/
BAUD_RATE_MAX
} XJ3100_BaudRate_t;
/* 初期化処理 */
void XJ3100_Init(void);
void XJ3100_WriteReg(uint8_t reg_idx, uint16_t value);
uint16_t XJ3100_ReadReg(uint8_t reg_idx);
/* データ入出力 */
void XJ3100_SendByte(uint8_t data);
uint8_t XJ3100_RecvByte(void);
/* ステータス取得 */
bool XJ3100_CheckRxPending(void);
bool XJ3100_CheckTxEmpty(void);
#endif /* XJ3100_DRV_H_ */
</code></pre></body></html>
実装ソース(xj3100_drv.c)
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html><html><body><pre><code>
#include "xj3100_drv.h"
#include "spi_hal.h"
#include "gpio_hal.h"
#include "delay.h"
/* 専用 GPIO ピンの切り替え */
static void ChipSelect_Set(bool active) {
if (active) {
GPIO_Clear(CS_PIN);
} else {
GPIO_Set(CS_PIN);
}
}
/**
* @brief 設定レジスタへの書き込み
*/
void XJ3100_WriteConfig(uint8_t hi_byte, uint8_t lo_byte) {
ChipSelect_Set(true);
SPI_Transfer(OP_CODE_CONFIG_WR);
SPI_Transfer(hi_byte);
SPI_Transfer(lo_byte);
ChipSelect_Set(false);
Delay_ms(5);
}
/**
* @brief 設定レジスタからの読み込み
*/
uint16_t XJ3100_ReadConfig() {
uint8_t buf[2];
ChipSelect_Set(true);
SPI_Transfer(OP_CODE_CONFIG_RD); /* アドレス 0x40 */
buf[0] = SPI_Transfer(0x00);
buf[1] = SPI_Transfer(0x00);
ChipSelect_Set(false);
Delay_ms(5);
return ((uint16_t)buf[0] << 8) | buf[1];
}
/**
* @brief データレジスタへの書き込み
*/
void XJ3100_Send(uint8_t byte_val, bool enable_tx_enable_bit) {
ChipSelect_Set(true);
if (enable_tx_enable_bit) {
SPI_Transfer(OP_CODE_DATA_WR | 0x04);
} else {
SPI_Transfer(OP_CODE_DATA_WR);
}
SPI_Transfer(byte_val);
ChipSelect_Set(false);
Delay_ms(5);
}
/**
* @brief データレジスタからの読み込み
*/
uint16_t XJ3100_ReceiveStatus() {
uint8_t h_byte, l_byte;
ChipSelect_Set(true);
SPI_Transfer(OP_CODE_DATA_RD);
h_byte = SPI_Transfer(0x00);
l_byte = SPI_Transfer(0x00);
ChipSelect_Set(false);
Delay_ms(5);
return ((uint16_t)h_byte << 8) | l_byte;
}
/**
* @brief バージョンアップ対応のためのボールドレート設定
*/
void XJ3100_SetBaudrate(XJ3100_BaudRate_t rate) {
uint16_t current = XJ3100_ReadConfig();
current &= ~MASK_BAUD_MASK;
current |= (uint16_t)rate;
/* 上位ビットの保持のため、分割書き込みが必要となる場合もあるが簡略化 */
XJ3100_WriteReg(0, current);
}
/**
* @brief FIFO エナブルフラグ設定
* @param enabled True:有効,False:無効
*/
void XJ3100_EnableFIFO(bool enabled) {
uint16_t reg = XJ3100_ReadConfig();
if (enabled) {
reg |= MASK_FEN_EN;
} else {
reg &= ~MASK_FEN_EN;
}
XJ3100_WriteReg(0, reg);
}
/**
* @brief シュットダウンモード制御
* @param shutdown True:シャットダウン,False:通常動作
*/
void XJ3100_ShutdownMode(bool shutdown) {
uint16_t reg = XJ3100_ReadConfig();
if (shutdown) {
reg |= MASK_SHDN_MODE;
} else {
reg &= ~MASK_SHDN_MODE;
}
XJ3100_WriteReg(0, reg);
}
/**
* @brief パリティチェック状態確認
* @return 奇数ビット数時の結果 (0=偶,1=奇)
*/
uint8_t XJ3100_GetParityBit() {
uint16_t stat = XJ3100_ReceiveStatus();
if (stat & MASK_PR_BIT) return 1;
return 0;
}
/**
* @brief RTS リンク制御
*/
void XJ3100_ControlRTS(bool state) {
// RTL の状態を保存し更新するロジック
// 簡略化のためここではステートマシン的な挙動のみ示唆
}
</code></pre></body></html>
4. 運用上の留意点
通信速度の設定においては、水晶発振器の周波数が正しく駆動されていることを前提とし、レジスタ内のボーレート選定要領と一致しているか確認してください。また、データ伝送中は CS ラインを高レベルに保つことなく、適切なタイミングでイネーブする必要があります。
エラーハンドリングについては、フレームエラーや受信アクティブの状態を確認するフラグを定期的に poll することで検知可能です。