【问题标题】:how to switch strings with pushbutton如何用按钮切换字符串
【发布时间】:2020-10-03 20:04:02
【问题描述】:

我正在使用带有 MSP430G2231 微控制器的 MSP-EXP430G2 板,并且我试图在按下按钮时使我的代码切换字符串。这是连接到BIT3

它像这样连接到液晶显示器:

Connections
P1.0 - D4 Pin11
P1.1 - D5 Pin12
P1.2 - D6 Pin13
P1.3 - D7 Pin14
P1.4 - RS Pin4
P1.5 - R/W Pin5
P1.6 - E Pin6
#define DR P1OUT = P1OUT | BIT4       // define RS high
#define CWR P1OUT = P1OUT & (~BIT4)   // define RS low
#define READ P1OUT = P1OUT | BIT5     // define Read signal R/W = 1 for reading
#define WRITE P1OUT = P1OUT & (~BIT5) // define Write signal R/W = 0 for writing
#define ENABLE_HIGH P1OUT = P1OUT | BIT6   // define Enable high signal
#define ENABLE_LOW P1OUT = P1OUT & (~BIT6) // define Enable Low signal
void set_input(void) {
  const unsigned char z = 0;
  switch (clock_input) {
  default:
    clock_input = 0;
  case 0:

    lcd_init();
    send_string("Frequency is");
    send_command(0xC0);
    break;
  case 1:

    lcd_init();
    send_string("Period is");
    send_command(0xC0);
    break;
  }
}

void main(void) {

  WDTCTL = WDTPW + WDTHOLD; // stop watchdog timer

  DCOCTL = 0;
  BCSCTL1 = CALBC1_1MHZ; // Set range
  DCOCTL = CALDCO_1MHZ;  // Set DCO step + modulation

  if (!(P1IN & BIT3)) { // Check if pushbutton down
    ++clock_input;      // Switch clock input
    set_input();        //                                                                                                                                                                                                                                                     
  }                                                                                                                                                                                                                                                                            
}

这是我的做法,也是我发送字符串的方式:

void send_string(char *s) {
  while (*s) {
    send_data(*s);
    s++;
  }
}

void send_command(unsigned char cmd) {
  check_busy();
  WRITE;
  CWR;
  P1OUT = (P1OUT & 0xF0) | ((cmd >> 4) & 0x0F); // send higher nibble
  data_write();                                 // give enable trigger
  P1OUT = (P1OUT & 0xF0) | (cmd & 0x0F);        // send lower nibble
  data_write();                                 // give enable trigger
}

void lcd_init(void) {
  P1DIR |= 0xFF;
  P1OUT &= 0x00;
  send_command(0x33);
  send_command(0x32);
  send_command(0x28); // 4 bit mode
  send_command(0x0E); // clear screen
  send_command(0x01); // cursor position
  send_command(0x06); // increment cursor
  send_command(0x80);
}

问题是当我将代码放入main 并按下按钮时没有任何反应。当我把它放在一个循环中时,它只是来回切换。我不知道板上的 Pin 1.3(S2) 是否有干扰 使用按钮,因为它们具有相同的名称(P1.3)。

【问题讨论】:

  • 按下按钮时观察调试器中的 GPIO 寄存器。如果他们不在那里切换,则与寄存器配置或硬件有关。并且请缩进你的代码,这是一团糟。

标签: c embedded msp430 iar lcd


【解决方案1】:

如果我们查看您的代码,就会发现一些非常重要的事情:

void main(void) {
  // just statements
  if (!(P1IN & BIT3)) {
    // just statements
  }                                                                                                                                                                                                                                                                            
}

您的代码不会循环。如果您让main 函数结束,会发生什么情况是微控制器停止执行代码,就像您告诉它停止一样。因此,您会在 main 末尾的每个微控制器项目中找到以下内容:

while(1){

}

因此应用程序将永远运行。如果你想在时间(或权力)结束之前完成一些事情,你必须将你的代码添加到 while 循环的主体中。

if (!(P1IN & BIT3)) {

这段代码完全没问题,可以添加到 while 循环体中,但请注意,while 循环的循环速度是 CPU 的速度减去执行循环体所需的时间。因此,它读取P1IN 的值太多以至于无法真正被感知。因此,您需要一个名为delay 的函数。这会使 CPU 在输入时间内保持忙碌,因此我们可以读取输入引脚并对其做出反应,而无需直接覆盖我们所做的工作。

目前这是delay 的一个足够好的版本:

void ms_delay(long milliseconds)
{
    int n;
    while(milliseconds--)
    {
        for (n=0 ; n<200 ; ++n);
    }
}

但在我们真正阅读之前,我们需要配置端口。这是通过DIR 寄存器完成的。当您将按钮连接到P1 时,我们将配置P1DIRP1DIR &amp;= ~BIT3(将位置 3 上的 P1Dir 设置为 0,其余部分保留)

现在我们可以读取P1IN 并获得BIT3 的值。

void ms_delay(long milliseconds)
{
    int n;
    while(milliseconds--)
    {
        for (n=0 ; n<16000 ; ++n) {} // please note that the 16000 value is very approximate and might need to be tweaked.
    }
}

void main(){
    // initialization of your hardware
    WDTCTL = WDTPW + WDTHOLD;
    P1DIR &= ~BIT3; // set bit 3 to 0 (INPUT) and leave the rest. (P1DIR = P1DIR & 11111011)

    while(1){
        ms_delay(100); // wait a 100 milliseconds
        if( P1IN & BIT3 == 1){
            // hurray the button is pressed. (if your button is connected to VCC at least.
        }
    }
}

上面的代码应该可以工作。但如果你不想让那些LED1LED2 亮起来,你需要在初始化代码中添加P1DIR |= BIT0 并将循环体更改为:

ms_delay(100); // wait a 100 milliseconds
if( P1IN & BIT3 == 1){
    P1OUT |= BIT0;
}
else{
    P1OUT &= ~BIT0;
}

至于您关于引脚冲突的问题。看来你有一个。 P1DIR |= 0xFF; 正在将 P1 端口配置为输出,但您想将 P1.3 用作输入,这样就不能一起工作了。

请随时寻找有关microcontrollers 的真实教程。如果您真的想了解有关微控制器的信息,请访问制造商的网站。在这种情况下,这是MSP,他们有几个文档可以帮助您。只需搜索微控制器部件号,您大部分时间都会找到它。重要文件有:

  1. Datasheet:简要描述微控制器功能和外围设备的通用文档。它还包含一些端口和注册信息。
  2. Family's User's Guide:有时被称为参考手册,这是一份全能的文档,其中 MSP 描述了如果想要控制微控制器需要知道的每一个细节。大多数内容并不那么有趣,但是如果您想做某事并且数据表中没有描述,那么用户指南是您的下一个选择。使用搜索功能,您很快就会找到它。

您提供的代码不完整,因为变量 clock_input 甚至没有在任何地方声明。

【讨论】: