Các lệnh trong lập trình MSP430

ctcngh

Thành Viên PIF
Theo mình để dịch trái bit thì mình có thể nhân 2.
P1OUT+=P1OUT;
Dịch phải thì có thể chia 2
P1OUT/=2;
 

Manhdd

Cố Vấn CLB
Staff member
Theo mình để dịch trái bit thì mình có thể nhân 2.
P1OUT+=P1OUT;
Dịch phải thì có thể chia 2
P1OUT/=2;
Cách này tuy đúng nhưng không nên dùng. Vì tập lệnh MCU (Lệnh Assembly) thường có sẵn các lệnh dịch bit, còn cách lệnh toán thì cùng lắm chỉ hỗ trợ đến cộng/trừ . Do vậy, chuyển lệnh dịch bit sang các lệnh nhân/chia làm lãng phí tài nguyên (Bộ nhớ+Thời gian xử lý) của hệ thống :)
 

phuong le

Thành Viên PIF
Tình hình là hôm nay mới nhận kit về và rất thích thú với việc vọc em nó. Tuy nhiên, vì mới làm quen với lập trình C cho MSP430 nên mình còn khá bỡ ngỡ. Vì vậy mình xin lập topic này để các bạn newmem như mình có thể trao đổi, thảo luận và học hỏi thêm.
Đầu tiên là mình hỏi về lệch dịch bit. Mình định làm dàn Led trong mạch chạy qua chạy lại, nhưng không biết cấu trúc của lệnh dịch là gì. Mình định xuất ra P1.
Cái thứ 2 là mình định cho P1.i với i chạy từ 0->7, như vậy có lệnh nào thực hiện điều đó không?
Ví dụ nếu viết theo pascal là
for i:=0 to 7 do
P1.i := 1;
:D
Sau khi xem mấy cái post mình có đóng góp thế này:
Vì con msp430g nó không có thanh ghi bit cho 1 PORT như trên PIC, hình như muốn xuất giá trị thì chỉ tác động lên P1OUT nên không thể dùng phép gắn cho cả PORT được.

Code gợi ý của mình như sau
Code:
P1DIR |= 0xFF;  // Set mode out mode cho P1
P1SEL = 0;      // Set mode GPIO
P1SEL2 = 0;
P1OUT &= ~0xFF;  // Reset all pins
 
while (1)
{
  unsigned char i, temp = 0x01;
  for (i=0; i<8; i++)
  {
    P1OUT &= ~0xFF;  // Reset all pins
    P1OUT |= temp;  // Set pins
    temp = temp << 1;
    _delay_cycles(100000);  // Delay 100 ms
  }
}
Với đoạn code trên thì nó sẽ thực hiện cháy từng led trên PORT LED, cứ sau 1 ms thì cháy 1 con theo thứ tự dịch sang trái (chú ý là do LED trên MAIN kích bằng mức 0 nên với code này nó sẽ sáng hết 7 led và chỉ tắt 1 led thôi) :D
ủa sao em copy i chang mà cái mạch e nó đơ như cây cơ ???
 

IceSandwich

Thành Viên PIF
Bạn đã tắt WatchDog Timer chưa vậy? Nếu không tắt thì sẽ không chạy được đâu.

Code:
// Stop watchdog timer to prevent time out reset
    WDTCTL = WDTPW + WDTHOLD;
:D
 

phuong le

Thành Viên PIF
Bạn đã tắt WatchDog Timer chưa vậy? Nếu không tắt thì sẽ không chạy được đâu.

Code:
// Stop watchdog timer to prevent time out reset
    WDTCTL = WDTPW + WDTHOLD;
:D
ò hjhj :D chạy đc òi ủa mà cái lệnh trên có ý nghĩa như thế nào a?
Code:
void main(void)
{
 
  P1DIR |= BIT0;
  P1DIR |= BIT6;
  WDTCTL = WDTPW + WDTHOLD;
  for (;;)
  {
    volatile unsigned int i;
    P1OUT ^= BIT0|BIT6;
 
    i = 50000;
    do (i--);
    while (i != 0);
  }
}
nếu e để nó trong code trên thì hai đền nhấp nháy có độ dừng, còn nếu ko có thì nhấp nháy liên tục???:-(
 
dòng
Code:
WDTCTL = WDTPW + WDTHOLD;
dùng để tắt WatchDog Timer nếu để nó còn hoạt động thì cứ sau một thời gian khi mà WatchDog Timer ràn thì nó sẽ tự động reset lại vdk nên code của em viết không có dòng đó thì sẽ bị reset liên tục. nên sẽ xin ra hiện tượng nháy liên tục.
 

mafiaWolf

Chủ tịch Hội phụ nữ PIF
Bạn đã tắt WatchDog Timer chưa vậy? Nếu không tắt thì sẽ không chạy được đâu.

Code:
// Stop watchdog timer to prevent time out reset
    WDTCTL = WDTPW + WDTHOLD;
:D
ò hjhj :D chạy đc òi ủa mà cái lệnh trên có ý nghĩa như thế nào a?
Code:
void main(void)
{
 
  P1DIR |= BIT0;
  P1DIR |= BIT6;
  WDTCTL = WDTPW + WDTHOLD;
  for (;;)
  {
    volatile unsigned int i;
    P1OUT ^= BIT0|BIT6;
 
    i = 50000;
    do (i--);
    while (i != 0);
  }
}
nếu e để nó trong code trên thì hai đền nhấp nháy có độ dừng, còn nếu ko có thì nhấp nháy liên tục???:-(
Nhìn code là thấy dân pro rồi :(.. CLB ta sắp có nhân tài mới :la:
 

phuong le

Thành Viên PIF
Bạn đã tắt WatchDog Timer chưa vậy? Nếu không tắt thì sẽ không chạy được đâu.

Code:
// Stop watchdog timer to prevent time out reset
    WDTCTL = WDTPW + WDTHOLD;
:D
ò hjhj :D chạy đc òi ủa mà cái lệnh trên có ý nghĩa như thế nào a?
Code:
void main(void)
{
 
  P1DIR |= BIT0;
  P1DIR |= BIT6;
  WDTCTL = WDTPW + WDTHOLD;
  for (;;)
  {
    volatile unsigned int i;
    P1OUT ^= BIT0|BIT6;
 
    i = 50000;
    do (i--);
    while (i != 0);
  }
}
nếu e để nó trong code trên thì hai đền nhấp nháy có độ dừng, còn nếu ko có thì nhấp nháy liên tục???:-(
Nhìn code là thấy dân pro rồi :(.. CLB ta sắp có nhân tài mới :la:
úi giời ạ :3cool_adore: copy cái này liếc cái kia mới ra cái code trên á :5cool_sweat:
 

phuong le

Thành Viên PIF
dòng
Code:
WDTCTL = WDTPW + WDTHOLD;
dùng để tắt WatchDog Timer nếu để nó còn hoạt động thì cứ sau một thời gian khi mà WatchDog Timer ràn thì nó sẽ tự động reset lại vdk nên code của em viết không có dòng đó thì sẽ bị reset liên tục. nên sẽ xin ra hiện tượng nháy liên tục.
à dậy chu kì nháy của nó mặc định là nhiêu a?
Code:
#include  <msp430g2553.h>
 
void main(void)
{
    WDTCTL = WDTPW + WDTHOLD;
  P1DIR |= BIT0;
  P1DIR |= BIT6;
 
  for (;;)
  {
  {
    volatile unsigned int i;
    P1OUT ^= BIT0|BIT6;
 
    i = 50000;
    do (i--);
    while (i != 0);
  }
  _delay_cycles(10000000);
  }
}
e thêm cai delay này vô thì 10s nháy lần, còn nếu không có lệnh delay thì mặc định là 1s hả a:botay:
 

cxduc92

Thành Viên PIF
phuong le: mình nói thế này cho bạn dễ hiểu .Tất cả các lệnh muốn thực hiện thì cần phải có 1 thời gian tương ứng.Trong máy thì gọi nó là chu kì máy-Machine cycle(MC)

Trong con msp 430g2553 1 chu kì máy là 1us (10^-6 s) .Mỗi lệnh mình giả sử là mất 1us để thực hiện(thực tế thì không phải lệnh nào cũng 1us).Như vậy 3 dòng lệnh :
{
i=50000;
do(i--);
while(i!=0);
}
thật ra chỉ là delay 50000MC= 50000 x 1u= 50 ms = 0.05 s (coi như bỏ qua 2 us của 2 dòng đầu)
Còn lệnh _delay_cycles(10 000 000) là 1 lệnh delay đc định nghĩa sẵn của g2553 .Ý nghĩa của _delay_cycles(n) là delay n MC.Lệnh của bạn có nghĩa là delay 10 000 000 MC= 10s.Vậy là cứ mỗi 10s nó đảo trạng thái
p/s: theo ý mình thì bạn chỉ cần sửa 1 chỗ là điều khiển đc tất cả các chu kì nhấp nháy này thôi
vd: bạn muốn nó cứ 1s nháy 1 lần=> n= 1/ (10^-6)=1 000 000.Như vậy
...
while(1)//for(;;)
{
P1OUT^=BIT1|BIT6;
_delay_cycles(1 000 000);
}
Thế là xong:1cool_byebye:
 

nhok 9x

Trứng gà
à, cho mình hỏi chút: cái lệnh nhảy đến nhãn cho trước trong đây là gì vậy? Vd trong 8051 là sjmp....
 

mafiaWolf

Chủ tịch Hội phụ nữ PIF
à, cho mình hỏi chút: cái lệnh nhảy đến nhãn cho trước trong đây là gì vậy? Vd trong 8051 là sjmp....
phải dùng lệnh máy thôi...go to.. mà hình như không ai xài nhiều :D
 

Manhdd

Cố Vấn CLB
Staff member
à, cho mình hỏi chút: cái lệnh nhảy đến nhãn cho trước trong đây là gì vậy? Vd trong 8051 là sjmp....
"Never use goto statement" : các lập trình viên ở ngôn ngữ cấp cao thường nhắc nhau như vậy =))
Ở khía cạnh ngôn ngữ máy, ASM, CPU cần các tập lệnh JMP để thực hiện rẽ nhánh và lặp. Tuy nhiên, với các ngôn ngữ có tính "người" hơn (C, C++, Java, ...) thì việc sử dụng GOTO làm mất tính cấu trúc của chương trình, khiến chương trình rất khó đọc và sửa chữa. Nhiều ngôn ngữ thậm chí không có lệnh GOTO. Các lệnh điều khiển rẽ nhánh và lặp trong c: if, switch-case, for, while, ... đều có thể thay thế GOTO và giúp chương trình có cấu trúc hơn :D
 

doancongthang

Thành Viên PIF
cho hỏi làm thế nào để config 2 timer, Timer A0 xùng xuất PWM qua chân p1.6.
Timer A1 đếm lên trong vòng 25ms.
anh em chỉ giáo.
void ConfigTimer(void)
{
CCTL0=CCIE; //CCR0 interrupt enabled
TA0CTL = TASSEL_2 + MC_1; // SMCLK, up mode
}
void ConfigPWM(void)
{
CCR0=1000; // PWM Period=50HZ
CCTL1 = OUTMOD_7; // CCR1 reset/set
CCR1=0; // PWM duty cycle
}
///////////////////////////////////////////////////////////////////////
void Configdemxung (void)
{
TA1CCTL0 = CCIE; // CCR0 interrupt enabled
TA1CCR0 = 25000;
TA1CTL = TASSEL_2 + MC_1; // SMCLK, upmode

}
và ngắt như thế này thì trong có hợp lí không
#pragma vector=TIMER1_A0_VECTOR
__interrupt void Timer1_A0 (void)
{Speed = pulse - pre_pulse; //so xung trong 25ms
pre_pulse = pulse;
Speed = (Speed*40*60)/400;
}
Timer A1 ngắt trong vòng 25ms
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer0_A0 (void)
{
//CCR1=CCR1+1; // Increace Duty Cycle
//if(CCR1==1001) CCR1=0; // If Duty Cycle =100%, reset it
CCR1 = Output;

}
Timer a0 xuất pwm theo chu kì là CCR1
 

honghiep

Cố Vấn CLB
Staff member
cho hỏi làm thế nào để config 2 timer, Timer A0 xùng xuất PWM qua chân p1.6.
Timer A1 đếm lên trong vòng 25ms.
anh em chỉ giáo.
void ConfigTimer(void)
{
CCTL0=CCIE; //CCR0 interrupt enabled
TA0CTL = TASSEL_2 + MC_1; // SMCLK, up mode
}
void ConfigPWM(void)
{
CCR0=1000; // PWM Period=50HZ
CCTL1 = OUTMOD_7; // CCR1 reset/set
CCR1=0; // PWM duty cycle
}
///////////////////////////////////////////////////////////////////////
void Configdemxung (void)
{
TA1CCTL0 = CCIE; // CCR0 interrupt enabled
TA1CCR0 = 25000;
TA1CTL = TASSEL_2 + MC_1; // SMCLK, upmode

}
và ngắt như thế này thì trong có hợp lí không
#pragma vector=TIMER1_A0_VECTOR
__interrupt void Timer1_A0 (void)
{Speed = pulse - pre_pulse; //so xung trong 25ms
pre_pulse = pulse;
Speed = (Speed*40*60)/400;
}
Timer A1 ngắt trong vòng 25ms
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer0_A0 (void)
{
//CCR1=CCR1+1; // Increace Duty Cycle
//if(CCR1==1001) CCR1=0; // If Duty Cycle =100%, reset it
CCR1 = Output;

}
Timer a0 xuất pwm theo chu kì là CCR1
Nhìn có vẻ là hợp lí. Nhưng nếu muốn xuất PWM cần config cho chân P1.6 nữa
 

thuyvy3110

Trứng gà
Cho em hỏi, đoạn code mẫu trong bài giảng C8, TA0CTL=TASSEL_2+MC_2+ID_3+TAIE; TACCR0=31250; //ngắt CCR0 khi đếm tới giá trị 31250 tương ứng với 0.25s so với giá trị đầu 0 của timer. Làm sao mà từ 0.25s tính ra 31250 ạ? em cũng đã làm tính công thức tới lui nhưng mà rối quá :botay:
 

gochit

Cố Vấn CLB
ID_3 là chọn chia clock cho 8, cho nên thời gian sẽ tính bằng 31250 *1/(1M/8)=0.25s :D
 
Top