This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
工具/软件:Code Composer Studio
你(们)好 我尝试使用 LCD 显示屏运行超声波传感器、以显示电流距离。 无论传感器前面是什么、我的结果都是0 cm。 请帮助我进行故障排除。 谢谢!
/******** //* uC 和超声波传感器连接 P1.4 -触发 P1.5 -回波 */ ******** //* UC 和 LCD 连接 TP1 - Vcc (+5V) TP3 - VSS (GND) P2.2 -中文 P2.3 - RS P2.4 - D4 P2.5 - D5. P2.6 - D6 P2.7 - D7 GND - RW GND - Ve/Vdd -通过1K 电阻器连接到 GND -此值决定对比度- 即、如果没有电阻器、所有点始终可见、而是 -较高的电阻意味着根本不显示点。 接地- K (LED-) VCC - A (LED+)+5V -用于背光 时钟:1MHz */ ******** /#include #include #include #include // uC GPIO 端口分配 #define uC_port P2OUT #define UC_PORT_DIR P2DIR //外设引脚分配 #define US_TRIG BIT4 #define US_echo Bit5 #define LCD_EN Bit2 #define LCD_RS BIT3 #define LCD_DATA BIT4 | BIT4 | BIT6 | BIT4 #define LCD_D0_OFFSET 4 // BIT4,因此它是4 #define US_MASK US_TRIG | US_ECHO #define LCD_MASK LCD_EN | LCD_RS | LCD_DATA unsigned int up_counter; unsigned int Distance_cm; // Timer A0捕获中断例程 P1.1 (回波)会导致调用此例程*/ #pragma vector=TIMER0_A0_vector __interrupt void TimerA0 (void) { IF (TA0CCTL0和 CCI) //上升沿 { UP_COUNTER = TA0CCR0; //将计数器复制到变量 } 其他 //下降沿 { //公式:以 cm 为单位的距离=(以 uec 为单位的时间)/58 Distance_cm =(TA0CCR0 - UP_COUNTER)/58; } TA0CCTL0 &=~CCIFG; TA0CTL &=~TAIFG; //清除中断标志-已处理 } void timer_init() { //将计时器 A0配置为读取回波信号: Timer A 捕获/比较控制0 => 捕捉模式:1 -双边沿+ 捕获同步+ 捕捉输入选择0 => P1.5 + 捕获模式+ 捕获比较中断使能*/ TA0CCTL0 |= CM_3 + SCS + CCIS_0 + CAP + CCIE; /* Timer A 控制配置=> 计时器 A 时钟源选择:1 - SMClock + Timer A 模式控制:2 -连续运行+ Timer A 时钟输入分频器0 -无分频器*/ TA0CTL |= tassel_2 + MC_2 + ID_0; //全局中断启用 _BIS_SR (GIE); } void LCD_reset () { uC_port = 0x00; _DELAY_CYCLES (20000); uC_port =(0x03 << LCD_D0_offset)| LCD_EN; uC_port &=~LCD_EN; _delay_cycles (10000); uC_port =(0x03 << LCD_D0_offset)| LCD_EN; uC_port &=~LCD_EN; _DELAY_CYCLES (1000); uC_port =(0x03 << LCD_D0_offset)| LCD_EN; uC_port &=~LCD_EN; _DELAY_CYCLES (1000); uC_port =(0x02 << LCD_D0_offset)| LCD_EN; uC_port &=~LCD_EN; __DELAY_CYCLES (1000); } void LCD_cmd (char cmd) { //发送上半字节 uC_port =((((cmd >> 4)& 0x0F)<< LCD_D0_offset)| LCD_EN; uC_port &=~LCD_EN; //发送低位半字节 uC_port =((cmd & 0x0F)<< LCD_D0_offset)| LCD_EN; uC_port &=~LCD_EN; __delay_cycles (4000); } void LCD_data (unsigned char dat) { //发送上半字节 uC_port =((((dat >> 4)和0x0F)<< LCD_D0_offset)| LCD_EN | LCD_RS); uC_port &=~LCD_EN; //发送低位半字节 uC_port =(((dat 和0x0F)<< LCD_D0_offset)| LCD_EN | LCD_RS); uC_port &=~LCD_EN; __DELAY_CYCLES (4000);//较小的延迟可能会导致缺少字符显示 } void LCD_init () { LCD_RESET(); //调用 LCD 复位 LCD_cmd (0x28); // 4位模式- 2行- 5x7字体。 LCD_cmd (0x0C); //不显示光标-不闪烁。 LCD_cmd (0x06); //自动增量—无显示移位。 LCD_cmd (0x80); //地址 DDRAM、偏移量为80h。 LCD_cmd (0x01); //清除屏幕 } void display_line (char *line) { while (*行) LCD_DATA (*线++); } void display_distance (char *线、int len) { while (len-) 如果(*行) LCD_DATA (*线++); 其他 lcd_data (''); } int main() { char Distance_string[4]; WDTCTL = WDTPW + WDTHOLD; //停止看门狗计时器 PM5CTL0 &=~LOCKLPM5; uC_PORT_DIR = LCD_MASK; // LCD 连接的输出方向 P1DIR |= US_TRIG; //触发到传感器的输出方向 P1DIR &=~US_ECHO; //传感器回波的输入方向 P1DIR &=~US_TRIG; //将触发器保持在低电平 P1SEL1 = US_ECHO; //从端口1将 US_echo 设置为计时器的触发器 //初始化 LCD lcd_init(); //初始化用于超声波距离感应的计时器 timer_init(); LCD_cmd (0x80);//选择第一行(0x80 + addr)-这里的 addr = 0x00 display_line ("距离计"); LCD_cmd (0xce);//选择第二行(0x80 + addr)-这里的 addr = 0x4e display_line ("cm"); while (1) { //测量距离 P1OUT ^= US_TRIG; //断言 _DELAY_CYCLES (10); // 10us 宽 P1OUT ^= US_TRIG; //断言 //_delay_cycles (60000); // 60ms 测量周期 _delay_cycles (60000); // 0.5sec 测量周期 //显示当前距离 sprintf (distance 字符串、"%d"、distance cm); LCD_cmd (0xcb);//选择第二行(0x80 + addr)-这里的 addr = 0x4b Display_Distance (Distance_string、3); } }
你(们)好
您使用哪种超声波?
您使用的通信接口是什么?
可以在调试模式下获取正确的数据吗?
此致
Gary
>
P1SEL1 = US_ECHO;
// set US_ECHO as trigger for Timer from Port-1
根据数据表(SLAS789C)表6-21、这会将 P1.5设置为 UCA0CLK (自动输出)。 添加:
>
P1SEL0 |= US_ECHO;
// P1.5 as TA0.0 (CCI0A) per SLAS789C Table 6-21
------
>
sprintf
(distance_string,
"%d"
, distance_cm);
65536/58 = 1129 (4位)、在这种情况下、此调用将溢出 Distance_string 并进入堆栈。
不要使用 sprintf (以前)。 请改用 snprintf。 并使 Distance_string[]更长。
------
[Edit: Noted in passing]
>
P1OUT ^= US_TRIG;
// assert
P1OUT 在复位时的值未定义、因此您不知道这条线在做什么。 (a)确保 P1OUT.4最初为低电平、或(b)改为使用"|="和"&="。 我建议(b)养成良好的习惯。
这是我的更新代码。 它不再显示0 cm。 它在338cm 处初始化。 几秒钟后、它显示118 cm、然后在118和119之间进行翻转斩波。 它不响应我的手移动。
/******** //* 项目:具有 LCD 显示屏的基于超声波的距离计 // *微控制器:MSP-EXP430G2 Launchpad 上的 MSP430G2231 */ /*超声波测距模块:HC-SR04 // //* 16x2 LCD 显示屏:1602K27-00 */ ******** / / //* uC 和超声波传感器连接 P1.4 -触发 P1.5 -回波 */ ******** //* UC 和 LCD 连接 TP1 - Vcc (+5V) TP3 - VSS (GND) P2.2 -中文 P2.3 - RS P2.4 - D4 P2.5 - D5. P2.6 - D6 P2.7 - D7 GND - RW GND - Ve/Vdd -通过1K 电阻器连接到 GND -此值决定对比度- 即、如果没有电阻器、所有点始终可见、而是 -较高的电阻意味着根本不显示点。 接地- K (LED-) VCC - A (LED+)+5V -用于背光 时钟:1MHz */ ******** /#include #include #include #include // uC GPIO 端口分配 //外设引脚分配 #define US_TRIG BIT4 #define US_echo Bit5 #define LCD_EN Bit2 #define LCD_RS BIT3 #define LCD_DATA BIT4 | BIT4 | BIT6 | BIT4 #define LCD_D0_OFFSET 4 // BIT4,因此它是4 #define US_MASK US_TRIG | US_ECHO #define LCD_MASK LCD_EN | LCD_RS | LCD_DATA unsigned int up_counter = 0; unsigned int distance _cm = 0; // Timer A0捕获中断例程 P1.1 (回波)导致调用此例程*/ #pragma vector=TIMER0_A0_vector __interrupt void TimerA0 (void) { IF (TA0CCTL0和 CCI) //上升沿 { UP_COUNTER = TA0CCR0; //将计数器复制到变量 } 其他 //下降沿 { //公式:以 cm 为单位的距离=(以 uec 为单位的时间)/58 Distance_cm =(TA0CCR0 - UP_COUNTER)/58; } TA0CCTL0 &=~CCIFG; TA0CTL &=~TAIFG; //清除中断标志-已处理 } void timer_init() { //将计时器 A0配置为读取回波信号: Timer A 捕获/比较控制0 => 捕捉模式:1 -双边沿+ 捕获同步+ 捕捉输入选择0 => P1.5 + 捕获模式+ 捕获比较中断使能*/ TA0CCTL0 |= CM_3 + SCS + CCIS_0 + CAP + CCIE; /* Timer A 控制配置=> 计时器 A 时钟源选择:1 - SMClock + Timer A 模式控制:2 -连续运行+ Timer A 时钟输入分频器0 -无分频器*/ TA0CTL |= tassel_2 + MC_2 + ID_0; //全局中断启用 _BIS_SR (GIE); } void LCD_reset () { P2OUT = 0x00; _DELAY_CYCLES (20000); P2OUT =(0x03 << LCD_D0_OFFSET)| LCD_EN; P2OUT &=~LCD_EN; _delay_cycles (10000); P2OUT =(0x03 << LCD_D0_OFFSET)| LCD_EN; P2OUT &=~LCD_EN; _DELAY_CYCLES (1000); P2OUT =(0x03 << LCD_D0_OFFSET)| LCD_EN; P2OUT &=~LCD_EN; _DELAY_CYCLES (1000); P2OUT =(0x02 << LCD_D0_OFFSET)| LCD_EN; P2OUT &=~LCD_EN; __DELAY_CYCLES (1000); } void LCD_cmd (char cmd) { //发送上半字节 P2OUT =((((cmd >> 4)& 0x0F)<< LCD_D0_OFFSET)| LCD_EN; P2OUT &=~LCD_EN; //发送低位半字节 P2OUT =((CMD 和0x0F)<< LCD_D0_OFFSET)| LCD_EN; P2OUT &=~LCD_EN; __delay_cycles (4000); } void LCD_data (unsigned char dat) { //发送上半字节 P2OUT =(((((dat >> 4)& 0x0F)<< LCD_D0_OFFSET)| LCD_EN | LCD_RS); P2OUT &=~LCD_EN; //发送低位半字节 P2OUT =((((dat 和0x0F)<< LCD_D0_OFFSET)| LCD_EN | LCD_RS); P2OUT &=~LCD_EN; __DELAY_CYCLES (4000);//较小的延迟可能会导致缺少字符显示 } void LCD_init () { LCD_RESET(); //调用 LCD 复位 LCD_cmd (0x28); // 4位模式- 2行- 5x7字体。 LCD_cmd (0x0C); //不显示光标-不闪烁。 LCD_cmd (0x06); //自动增量—无显示移位。 LCD_cmd (0x80); //地址 DDRAM、偏移量为80h。 LCD_cmd (0x01); //清除屏幕 } void display_line (char *line) { while (*行) LCD_DATA (*线++); } void display_distance (char *线、int len) { while (len-) 如果(*行) LCD_DATA (*线++); 其他 lcd_data (''); } int main() { char Distance_string[10]; WDTCTL = WDTPW | WDTHOLD; //停止看门狗计时器 PM5CTL0 &=~LOCKLPM5; P2DIR = LCD_MASK; // LCD 连接的输出方向 P1DIR |= US_TRIG; //触发到传感器的输出方向 P1DIR &=~US_ECHO; //传感器回波的输入方向 P1DIR &=~US_TRIG; //将触发器保持在低电平 P1SEL1 = US_ECHO; //从端口1将 US_echo 设置为计时器的触发器 P1SEL0 |= US_ECHO; //初始化 LCD lcd_init(); //初始化用于超声波距离感应的计时器 timer_init(); LCD_cmd (0x80);//选择第一行(0x80 + addr)-这里的 addr = 0x00 display_line (" distance "); LCD_cmd (0xce);//选择第二行(0x80 + addr)-这里的 addr = 0x4e display_line ("cm"); while (1) { //测量距离 P1OUT |= US_TRIG; //断言 _DELAY_CYCLES (10); // 10us 宽 P1OUT |= US_TRIG; //断言 //_delay_cycles (60000); // 60ms 测量周期 _DELAY_CYCLES (50000); // 0.5sec 测量周期 //显示当前距离 snprintf (Distance_string、10、"%d"、Distance_cm); LCD_cmd (0xcb);//选择第二行(0x80 + addr)-这里的 addr = 0x4b Display_Distance (Distance_string、3); } }
>
P1DIR &= ~US_TRIG;
// keep trigger at low
这会将触发器重新转换为输入。 我怀疑您的意思是相反
>
P1OUT &= ~US_TRIG;
// keep trigger at low
------------------
>
P1OUT |= US_TRIG;
// deassert
这只会使引脚保持高电平。 尝试:
>
P1OUT &= ~US_TRIG;
// deassert (low)
谢谢! 超声波无法正常工作的解决方案!