配置SCI

配置引脚,支持中断+FIFO

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
void initSCIAFIFO(void)
{
// 配置GPIO引脚
GPIO_setMasterCore(43, GPIO_CORE_CPU1);
GPIO_setPinConfig(GPIO_43_SCIRXDA);
GPIO_setDirectionMode(43, GPIO_DIR_MODE_IN);
GPIO_setPadConfig(43, GPIO_PIN_TYPE_STD);
GPIO_setQualificationMode(43, GPIO_QUAL_ASYNC);

GPIO_setMasterCore(42, GPIO_CORE_CPU1);
GPIO_setPinConfig(GPIO_42_SCITXDA);
GPIO_setDirectionMode(42, GPIO_DIR_MODE_OUT);
GPIO_setPadConfig(42, GPIO_PIN_TYPE_STD);
GPIO_setQualificationMode(42, GPIO_QUAL_ASYNC);

// 配置SCI模块
SCI_disableModule(SCIA_BASE);
SCI_performSoftwareReset(SCIA_BASE);

SCI_setConfig(SCIA_BASE, DEVICE_LSPCLK_FREQ, 115200,
(SCI_CONFIG_WLEN_8 | SCI_CONFIG_STOP_ONE | SCI_CONFIG_PAR_NONE));

// 配置FIFO
SCI_enableFIFO(SCIA_BASE);
SCI_resetTxFIFO(SCIA_BASE);
SCI_setFIFOInterruptLevel(SCIA_BASE, SCI_FIFO_TX8, SCI_FIFO_RX4);

SCI_enableModule(SCIA_BASE);
}

全局中断配置,在main函数里边初始化中断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void main(void)
{
// 初始化设备
Device_init();
Device_initGPIO();
Board_init();

// 初始化SCI
initSCIAFIFO();

// 初始化中断
Interrupt_initModule();
Interrupt_initVectorTable();
Interrupt_register(INT_SCIA_TX, sciaTXFIFOISR);
Interrupt_enable(INT_SCIA_TX);

......

}

实现发送中断服务函数,跟阻塞式发送不一样的是,我们需要使用非阻塞式接口:SCI_writeCharNonBlocking

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
__interrupt void sciaTXFIFOISR(void)
{
while((txBufferIndex < txDataCount) && (SCI_getTxFIFOStatus(SCIA_BASE) != SCI_FIFO_TX15))
{
SCI_writeCharNonBlocking(SCIA_BASE, txBuffer[txBufferIndex++]);
}

if((txBufferIndex >= txDataCount) && (SCI_getTxFIFOStatus(SCIA_BASE) == SCI_FIFO_TX0))
{
isTransmitting = false;
SCI_disableInterrupt(SCIA_BASE, SCI_INT_TXFF);
}

SCI_clearInterruptStatus(SCIA_BASE, SCI_INT_TXFF);
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
}

JustFloat

自定义单帧数据类型:Float类型数据,使用union是为了方便通过uint16_t的方式进行序列化

1
2
3
4
5
6
7
8
9
// 全局变量定义
#define TX_BUFFER_SIZE 32
#define CH_COUNT 5
#define PI 3.14159265358979323846f

typedef union {
float DataFloat;
uint16_t DataUint16[2];
} FloatUnion;

实现单帧数据的发送:确保帧尾能对的上,每一次发送都要发送使能中断,第一次需要手动触发发送中断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
void SCIA_sendFrame(float chn1, float chn2, float chn3, float chn4, float chn5)
{

while(isTransmitting) { }

FloatUnion data[CH_COUNT];

data[0].DataFloat = chn1;
data[1].DataFloat = chn2;
data[2].DataFloat = chn3;
data[3].DataFloat = chn4;
data[4].DataFloat = chn5;

txBufferIndex = 0;
txDataCount = 0;

int i;
for(i = 0; i < CH_COUNT; i++)
{
txBuffer[txDataCount++] = (uint8_t)(data[i].DataUint16[0] & 0xFF);
txBuffer[txDataCount++] = (uint8_t)((data[i].DataUint16[0] >> 8) & 0xFF);
txBuffer[txDataCount++] = (uint8_t)(data[i].DataUint16[1] & 0xFF);
txBuffer[txDataCount++] = (uint8_t)((data[i].DataUint16[1] >> 8) & 0xFF);
}

// 添加帧尾 (00 00 80 7F)
txBuffer[txDataCount++] = 0x00;
txBuffer[txDataCount++] = 0x00;
txBuffer[txDataCount++] = 0x80;
txBuffer[txDataCount++] = 0x7F;

// 开始传输
isTransmitting = true;
txBufferIndex = 0;
SCI_enableInterrupt(SCIA_BASE, SCI_INT_TXFF);

// 手动触发第一次发送
while((txBufferIndex < txDataCount) && (SCI_getTxFIFOStatus(SCIA_BASE) != SCI_FIFO_TX15))
{
SCI_writeCharNonBlocking(SCIA_BASE, txBuffer[txBufferIndex++]);
}
}

模拟数据

我们来实现模拟数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 主循环
float angle = 0.0f; // 从0开始
while(1)
{
float normalized_angle = normalize_angle(angle);
float sin_val;
float cos_val;

// 计算三角函数值并限制范围
sin_val = limit_range(sinf(normalized_angle), -1.0f, 1.0f);
cos_val = limit_range(cosf(normalized_angle*2), -1.0f, 1.0f);

SCIA_sendFrame(angle, round_to_2_decimal(sin_val), round_to_2_decimal(sin_val+cos_val),
limit_range(round_to_2_decimal(sin_val * cos_val), -1.0f, 1.0f),
limit_range(round_to_2_decimal(cos_val * cos_val), 0.0f, 1.0f));

angle += 0.1f;

DEVICE_DELAY_US(10);
}

值得一提的是,三角函数它是通过查表法来实现的,angle值太大会有误差,我们需要设计归一化函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// 将角度归一化到[-2π, 2π]范围内
float normalize_angle(float angle)
{
const float two_pi = 2.0f * PI;
float normalized = fmodf(angle, two_pi);
if(normalized < -PI) normalized += two_pi;
if(normalized > PI) normalized -= two_pi;
return normalized;
}

// 保留2位小数的函数
float round_to_2_decimal(float value)
{
// 使用更稳定的舍入方法
const float factor = 100.0f;
float temp = value * factor;

// 处理正负数
if(temp >= 0.0f) {
temp = floorf(temp + 0.5f);
} else {
temp = ceilf(temp - 0.5f);
}

// 避免除以0
if(fabsf(temp) < 1e-6f) {
return 0.0f;
}

return temp / factor;
}

// 限制数值范围的函数
float limit_range(float value, float min, float max)
{
if(value > max) return max;
if(value < min) return min;
return value;
}

运行效果

VOFA+的实时运行效果:显示5个通道的波形数据

img


© 2025 hywing 使用 Stellar 创建
总访问 113701 次 | 本页访问 326