工具/软件:
简短说明:尝试通过 USB 转 UART 桥接器从笔记本电脑与微控制器进行通信。 GUI Composer 会自动选择带调试探针的 COM 端口、但我们需要使用菜单中显示为 Microsoft 的 USB 转 UART 桥接 COM 端口、不允许我们连接到该端口。 我们将选择它、但在运行 GUI Composer 时、它会自动切换回调试探针。
详细说明:我们将尝试使用 来自 TI GUI Composer 的 USB 转 UART 桥接器与 F280049C 电路板进行通信。 我们可以在 CCS 上运行电路板代码时运行 Tera Term 并有效地通信、但在尝试配置 TI GUI 以识别 USB-UART 通信路径、而不是典型的调试探针时、我们无法连接到 COM 端口、要么卡在调试 COM 端口上、要么收到错误消息称它无法连接到电路板。 经过一些研究,我们已经看到我们需要创建一个 JavaScript 语言转换方法? 下面的代码没有任何语言转换更改,但它完成了我们希望它使用 tera 术语的任务。 本质上、程序将使用随机数生成器来模拟传感器的读数、然后在终端中您可以键入:“position_cmd:(此处的任意数字)“、它会将输出到终端的变量更新为您刚刚键入的数字。 在 TI GUI 上、我需要一个文本框、可以在其中键入我希望 position_cmd 的数字、然后我也会在 TI GUI Composer 的折线图上看到该输出。 是否可以与 TI GUI 通信、或者我们是否必须创建自己的自定义接口?
#include "driverlib.h"
#include "device.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#define INPUT_BUF_LEN 32
#define POSITION_MIN 0
#define POSITION_MAX 100
#define PRINT_PERIOD_MS 500 // Print every 500 ms
#define RANDOM_PERIOD_MS 2000 // New random every 2000 ms
#define HOLD_PERIOD_MS 2000 // Hold manual value for 2000 ms
volatile uint16_t position = 0;
volatile uint16_t print_flag = 0;
volatile uint16_t random_flag = 0;
volatile uint16_t manual_hold_active = 0;
volatile uint16_t hold_elapsed_ms = 0;
void initTimers(void);
__interrupt void printTimerISR(void);
__interrupt void randomTimerISR(void);
uint16_t pseudo_random(uint16_t seed);
void main(void)
{
uint16_t receivedChar;
unsigned char inputBuffer[INPUT_BUF_LEN];
uint16_t idx;
char msg[64];
uint16_t seed = 1234; // Arbitrary seed
Device_init();
Device_initGPIO();
// SCI GPIO configuration (SCIB RX: GPIO13, TX: GPIO40)
GPIO_setControllerCore(13, GPIO_CORE_CPU1);
GPIO_setPinConfig(GPIO_13_SCIB_RX);
GPIO_setDirectionMode(13, GPIO_DIR_MODE_IN);
GPIO_setPadConfig(13, GPIO_PIN_TYPE_STD);
GPIO_setQualificationMode(13, GPIO_QUAL_ASYNC);
GPIO_setControllerCore(40, GPIO_CORE_CPU1);
GPIO_setPinConfig(GPIO_40_SCIB_TX);
GPIO_setDirectionMode(40, GPIO_DIR_MODE_OUT);
GPIO_setPadConfig(40, GPIO_PIN_TYPE_STD);
GPIO_setQualificationMode(40, GPIO_QUAL_ASYNC);
Interrupt_initModule();
Interrupt_initVectorTable();
// Register ISRs
Interrupt_register(INT_TIMER0, &printTimerISR);
Interrupt_register(INT_TIMER1, &randomTimerISR);
// Initialize timers
initTimers();
SCI_performSoftwareReset(SCIB_BASE);
SCI_setConfig(SCIB_BASE, DEVICE_LSPCLK_FREQ, 9600, (SCI_CONFIG_WLEN_8 |
SCI_CONFIG_STOP_ONE |
SCI_CONFIG_PAR_NONE));
SCI_resetChannels(SCIB_BASE);
SCI_resetRxFIFO(SCIB_BASE);
SCI_resetTxFIFO(SCIB_BASE);
SCI_clearInterruptStatus(SCIB_BASE, SCI_INT_TXFF | SCI_INT_RXFF);
SCI_enableFIFO(SCIB_BASE);
SCI_enableModule(SCIB_BASE);
SCI_performSoftwareReset(SCIB_BASE);
// Enable timer interrupts
Interrupt_enable(INT_TIMER0);
Interrupt_enable(INT_TIMER1);
CPUTimer_enableInterrupt(CPUTIMER0_BASE);
CPUTimer_enableInterrupt(CPUTIMER1_BASE);
EINT;
ERTM;
// Initial random position
position = pseudo_random(seed) % (POSITION_MAX - POSITION_MIN + 1) + POSITION_MIN;
for (;;)
{
// Print position every 500 ms
if (print_flag)
{
snprintf(msg, sizeof(msg), "\r\nThe position is %u radians\n", position);
SCI_writeCharArray(SCIB_BASE, (uint16_t*)msg, strlen(msg));
print_flag = 0;
}
// Update position randomly every 2000 ms (if not in manual hold)
if (random_flag)
{
if (!manual_hold_active)
{
static uint16_t rand_seed = 0;
rand_seed++;
position = pseudo_random(rand_seed) % (POSITION_MAX - POSITION_MIN + 1) + POSITION_MIN;
}
random_flag = 0;
}
// Check for incoming data (non-blocking)
if (SCI_getRxFIFOStatus(SCIB_BASE) != SCI_FIFO_RX0)
{
idx = 0;
while (1)
{
receivedChar = SCI_readCharBlockingFIFO(SCIB_BASE);
SCI_writeCharBlockingFIFO(SCIB_BASE, receivedChar); // Echo
if (receivedChar == '\r' || receivedChar == '\n')
{
inputBuffer[idx] = '\0';
break;
}
if (idx < INPUT_BUF_LEN - 1)
{
inputBuffer[idx++] = (unsigned char)receivedChar;
}
}
// Parse command
if (strncmp((char*)inputBuffer, "position_cmd:", 13) == 0)
{
int new_pos = atoi((char*)inputBuffer + 13);
if (new_pos >= POSITION_MIN && new_pos <= POSITION_MAX)
{
position = (uint16_t)new_pos;
manual_hold_active = 1;
hold_elapsed_ms = 0;
snprintf(msg, sizeof(msg), "\r\nThe position is %u radians\n", position);
SCI_writeCharArray(SCIB_BASE, (uint16_t*)msg, strlen(msg));
}
}
}
}
}
// Simple pseudo-random number generator (linear congruential)
uint16_t pseudo_random(uint16_t seed)
{
static uint16_t lfsr = 0;
if (seed != 0) lfsr = seed;
lfsr = (lfsr * 1103515245 + 12345) & 0x7FFF;
return lfsr;
}
// Initialize two timers: one for printing, one for random update
void initTimers(void)
{
// Timer0: Print every 500 ms
uint32_t print_cycles = (DEVICE_SYSCLK_FREQ / 1000) * PRINT_PERIOD_MS - 1;
CPUTimer_setPeriod(CPUTIMER0_BASE, print_cycles);
CPUTimer_setPreScaler(CPUTIMER0_BASE, 0);
CPUTimer_reloadTimerCounter(CPUTIMER0_BASE);
CPUTimer_startTimer(CPUTIMER0_BASE);
// Timer1: Random update every 2000 ms
uint32_t random_cycles = (DEVICE_SYSCLK_FREQ / 1000) * RANDOM_PERIOD_MS - 1;
CPUTimer_setPeriod(CPUTIMER1_BASE, random_cycles);
CPUTimer_setPreScaler(CPUTIMER1_BASE, 0);
CPUTimer_reloadTimerCounter(CPUTIMER1_BASE);
CPUTimer_startTimer(CPUTIMER1_BASE);
}
// Timer0 ISR: set print flag every 500 ms, manage manual hold timer
__interrupt void printTimerISR(void)
{
print_flag = 1;
if (manual_hold_active)
{
hold_elapsed_ms += PRINT_PERIOD_MS;
if (hold_elapsed_ms >= HOLD_PERIOD_MS)
{
manual_hold_active = 0;
hold_elapsed_ms = 0;
}
}
CPUTimer_reloadTimerCounter(CPUTIMER0_BASE);
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1);
}
// Timer1 ISR: set random flag every 2000 ms
__interrupt void randomTimerISR(void)
{
random_flag = 1;
CPUTimer_reloadTimerCounter(CPUTIMER1_BASE);
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1);
}