基于TMS320F28335的SND3360变量显示及PWM控制技术求助
问题描述
我正在使用TI的TMS320F28335实现永磁同步电机(PMSM)的矢量控制,需要通过连接SND3360的按键实现PWM的启停控制,同时要在SND3360上显示变量数据。目前已能在SND3360上显示固定数值,但不清楚如何实现变量值的显示,现附上相关代码片段,恳请提供代码层面的帮助。
当前代码片段
模式切换逻辑
Mode_cnt += Mode_inc; if(Mode_cnt > MODE_LIM) { Mode_cnt = 0; } switch(Mode_cnt) { case 0: Display[5] = 0x30; break; case 1: sts_display(); led_display(0x00); DELAY_US(2L); break; case 2: diag_display(); led_display(0x00); DELAY_US(2L); break; case 3: para1_display(); led_display(0x00); DELAY_US(2L); break; } }
固定值显示示例
void sts_display(void) { Sts_cnt += Up_inc; if(Sts_cnt > Sts_lim) { Sts_cnt = 0; } switch(Sts_cnt) { case 0: Display[3] = 0x30; break; case 1: Display[3] = 0x75; break; case 2: Display[3] = 0x36; break; default: Display[3] = 0x30; break; } }
通过这些函数,我可以对特定按键及Display[n](n=1...6)进行设置、清除、递增和递减操作。
解决方案
要实现变量值显示,核心是把变量的数值转换为SND3360数码管对应的段码,再赋值给Display数组。以下是具体实现步骤和代码:
1. 定义数码管段码映射表
先确认SND3360数码管类型(共阴/共阳),以下以共阴七段码为例(共阳则将段码取反):
// 共阴段码:0-9、A-F(覆盖整数和十六进制显示需求) const unsigned char SEG_CODE[] = {0x30, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71};
2. 实现变量转段码的通用函数
整数转段码函数
支持多位数显示,可处理正负数:
// 将整数val拆分到Display的start_pos位置,显示digit_len位 void display_int(int val, unsigned char start_pos, unsigned char digit_len) { unsigned char i; unsigned long abs_val; // 处理负数:先显示负号 if(val < 0) { Display[start_pos] = 0x40; // 负号对应的段码 abs_val = -val; start_pos++; digit_len--; } else { abs_val = val; } // 从高位到低位拆分数字并赋值段码 for(i = 0; i < digit_len; i++) { unsigned char digit = (abs_val / pow(10, digit_len - 1 - i)) % 10; Display[start_pos + i] = SEG_CODE[digit]; } }
浮点数转段码函数
通过放大倍数将小数转为整数显示,支持带小数位的变量(如母线电压、转速):
// 显示浮点数val:int_digit位整数,dec_digit位小数,起始位置start_pos void display_float(float val, unsigned char start_pos, unsigned char int_digit, unsigned char dec_digit) { int int_part = (int)val; int dec_part = (int)((val - int_part) * pow(10, dec_digit)); // 显示整数部分 display_int(int_part, start_pos, int_digit); // 显示小数点(通过点亮数码管的小数点段,此处假设段码加0x80实现) if(dec_digit > 0) { Display[start_pos + int_digit] |= 0x80; // 显示小数部分 display_int(dec_part, start_pos + int_digit + 1, dec_digit); } }
3. 修改显示函数实现变量显示
以para1_display()为例,实现电机转速、相电流等变量的切换显示:
// 假设已定义全局变量:motor_speed(转速)、phase_current_a(A相电流)、bus_voltage(母线电压) void para1_display(void) { Sts_cnt += Up_inc; if(Sts_cnt > Sts_lim) { Sts_cnt = 0; } switch(Sts_cnt) { case 0: display_int(motor_speed, 1, 4); break; // 1-4位显示转速(0-9999) case 1: display_int(phase_current_a, 1, 4); break; // 显示A相电流 case 2: display_float(bus_voltage, 1, 3, 1); break; // 显示母线电压(3位整数+1位小数) default: display_int(motor_speed, 1, 4); break; } }
4. 按键控制PWM启停
在按键扫描函数中添加PWM启停逻辑:
// 按键扫描函数(需根据SND3360硬件实现,返回按键状态) unsigned char scan_snd3360_key(void) { // 此处补充SND3360按键扫描代码,返回KEY_OK/KEY_UP/KEY_DOWN等状态 return KEY_NONE; } // 按键处理:控制PWM启停 void key_control_pwm(void) { static unsigned char pwm_running = 0; // 0:停止,1:运行 unsigned char key = scan_snd3360_key(); if(key == KEY_OK) { pwm_running = !pwm_running; if(pwm_running) { // 启动PWM:配置F28335的PWM寄存器 EALLOW; EPwm1Regs.TBCTL.bit.CTRMODE = 0; // 增计数模式 EPwm1Regs.AQCTLA.bit.CAU = AQ_SET; // 计数器等于CMPA时置高 EPwm1Regs.AQCTLA.bit.CAD = AQ_CLEAR; // 计数器等于CMPA时置低 EDIS; } else { // 停止PWM:禁用输出动作 EALLOW; EPwm1Regs.AQCTLA.bit.CAU = AQ_NO_ACTION; EPwm1Regs.AQCTLA.bit.CAD = AQ_NO_ACTION; EDIS; } } }
5. 主循环整合逻辑
在主循环中定期执行按键处理和显示更新:
void main(void) { // 初始化:系统时钟、GPIO、PWM、SND3360等 system_init(); snd3360_init(); while(1) { key_control_pwm(); // 处理PWM启停按键 // 更新显示模式 Mode_cnt += Mode_inc; if(Mode_cnt > MODE_LIM) { Mode_cnt = 0; } switch(Mode_cnt) { case 0: Display[5] = 0x30; break; case 1: sts_display(); led_display(0x00); DELAY_US(2L); break; case 2: diag_display(); led_display(0x00); DELAY_US(2L); break; case 3: para1_display(); led_display(0x00); DELAY_US(2L); break; } snd3360_refresh(); // 刷新SND3360显示(根据硬件要求添加) } }
内容的提问来源于stack exchange,提问作者Muhammad
相关产品推荐
相关产品推荐

