Được tạo bởi Blogger.

Labels

Thứ Sáu, 14 tháng 10, 2016

TivaC - GPIO


Hiểu về GPIO


Trong phần này tôi sẽ chỉ cho bạn về các tính năng của modul GPIO có trên kit TM4C123. Các MCU khác của Tiva cũng có GPIO tương tự nhưng có thể có nhiều hoặc ít hơn modul hoặc tính năng nên tốt nhất là luôn luôn tham khảo datasheet để có đầy đủ thông tin. Tôi sẽ không đề cập tới các thanh ghi là vì để hiểu cách lập trình với TivaWare (Thư viện có sẵn dùng để hỗ trợ lập trình với kit Tiva). Các bảng để tham khảo luôn lấy từ TM4C123GH6PM MCU.

Nội dung:
+ Tổng quan về GPIO
+ Blinky với TivaWare
+ Đầu vào số đơn giản
+ Đầu vào số với NGẮT
+ Ví dụ về điều khiển màu sắc bóng đèn RGB

GPIO là gì?

GPIO là viết tắt của General Purpose Input/Outputs (Các IO với mục đích chung), nghĩa là nó là một modul có khả năng nhận hoặc truyền tín hiệu. Chúng làm việc với tín hiệu số nhưng có thể trở thành bộ trộn để sử dụng các pin (chân) với các ngoại vi khác như ADC, SSI, UART,...

Thông số kỹ thuật của Tiva GPIO

IC TM4C123GH6PM có 6 khối GPIO, mỗi khối có cổng riêng (port A, port B, port C, port D, port E, port F).
Các thông số kỹ thuật như dưới đây:
    + Lên tới 43 GPIO, phụ thuộc vào cấu hình
    + Tính linh hoạt cao cho phép sử dụng như GPIO hoặc một chuỗi các chức năng ngoại vi khác
    + 5V trong cấu hình đầu vào
    + Các port từ A-G được truy cập thông qua Advanced Peripheral Bus (APB)
    + Khả năng chuyển mạch nhanh ở mỗi chu kỳ xung clock cho các cổng trên AHB, mỗi hai chu kỳ  clock cho các port trên APB.
    + Điều khiển khả trình cho các ngắt GPIO
       - Bộ ngắt chung
       - Bộ kích ngắt trên cạnh lên, cạnh xuống hoặc cả hai
       - Độ nhạy ở giá trị cao hoặc thấp
    + Bit mặt nạ trên cả bộ đọc và viết thông qua các đường địa chỉ.
    + Có thể được sử dụng để khởi tạo một tần số lấy mẫu ADC hoặc một bộ truyền uDMA
    + Trạng thái chân có thể được giữ lại trong suốt chế độ ngủ
    + Các chân được cấu hình như đầu vào số  được kích hoạt Schmitt.
    + Điều khiển khả trình cho cấu hình các chân GPIO
       - Kéo điện trở lên hoặc xuống
       - 2mA, 4mA và 8mA cho giao tiếp số. Lên tới 4 chân có thể tạo ra dòng 18mA cho các ứng dụng cần dòng lớn
       - Điều khiển tốc độ Slew cho 8mA
       - Kích hoạt Open drain
       - Kích hoạt đầu vào số

Đó là các thông số kỹ thuật, nó có một số thứ rất tuyệt phải không, chẳng hạn như gần như tất cả các GPIO đều là 5V, một truy cập nhanh hơn bằng các gọi AHB và các biến ngắt trong tất cả GPIO. Chú ý răng chân PD4, PD5, PB0 và PB1 không là 5V và đầu vào tối đa là 3.6V.

Mỗi GPIO có 8 chân nên có tổng số là 48 chân nhưng một số là chân nội và không thể được sử dụng nên tối đa có 43 có thể được sử dụng. Vì lý do vật lý mà các kit thường có ít hơn vậy. Kit TM4C123 GH6PM chỉ có 37 chân GPIO.

Các chức năng thay thế

GPIO cho phép vi điều khiển của bạn giao tiếp với bên ngoài. Nó cho phép các đầu vào hoặc đầu ra số và cũng cho phép các chức năng thay thế. Vậy chúng là gì?
Các chức năng thay thế có thể được đọc các tín hiệu tương tự bằng cách sử dụng các chân ADC hoặc giao tiếp UART bằng cách cấu hình.
Các chức năng có sẵn phụ thuộc vào chân và bạn có thể thấy chúng trong bảng dưới đây:


Mỗi khi bạn muốn sử dụng một ngoại vi như modul PWM hoặc ADC, bạn cần sử dụng chân tương ứng. Nhớ là phải cài đặt GPIO với cùng chức năng thay thế.

Đặc biệt quan trọng: Các chân GPIO với sự xem xét đặc biệt

Một số chân bị khóa để có cấu hình chắc chắn và chỉ có thể được sử dụng nếu bạn mở khóa chúng. Bạn cần làm điều này trong thanh ghi GPIOLOCK và giải thoát chúng bằng cách cài đặt thanh ghi GPIOCR. Nếu bạn sử dụng TivaWare, chỉ cần làm như dưới đây:

HWREG(GPIO_PORTx_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY ;
HWREG(GPIO_PORTx_BASE + GPIO_O_CR)  |= 0x80;


Như vậy, bạn đã có cái nhìn tổng quan và hiểu cơ bản về GPIO trên dòng TivaC. Trong phần tiếp theo sẽ là một số ví dụ lập trình với GPIO. Bạn sẽ hiểu rõ hơn cách sử dụng TivaWare để lập trình cho TM4C123GH6PM.


Blinky với TivaWare

Trong phần này tôi sẽ chỉ cho bạn cách để nhấp nhảy một đèn led với kit TM4C123. 
Đèn led bạn sẽ sử dụng là red LED được kết nối với chân PF1 có sẵn trên kit. Bạn có thể xem rõ hơn từ kit user guide của hãng.
Ví dụ này được tạo bằng phần mềm CCS của hãng TI. Bạn nên tham khảo TivaWare Peripheral Driver Library USER’S GUIDE của hãng để hiểu rõ hơn về các câu lệnh sử dụng trong các ví dụ.

+ Đầu tiên, chúng ta cần phải cài đặt clock của hệ thống. Câu lệnh sau sẽ cài đặt chip chạy với tốc độ 80Mhz

SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XT AL_16MHZ);

+ Tiếp theo, chúng ta cần enable clock của ngoại vi. 

SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); 
SysCtlDelay(3);

Thông thường, clock ở trạng thái disable để tiết kiệm năng lượng nên để sử dụng một ngoại vi bạn cần enable chúng. Tiếp theo đến dòng lệnh delay, tôi khuyên bạn nên chờ ít nhất 3 chu kỳ xung clock trước khi việc cấu hình thực sự được enable. 
    - SysCtlPeripheralEnable(uint32_t ui32Peripheral) là lệnh bạn luôn sử dụng để enable một ngoại vi. Nó enable xung clock cho ngoại vi. Biến truyền vào là ngoại vi bạn muốn enable. Đối với GPIO thì SYSCTL_PERIPH_GPIOx x ở đây là ký tự của ngoại vi bạn muốn kích hoạt.
    - SysCtlDelay(uint32_t ui32Count) là một hàm delay. Nó dừng code trong một số chu kỳ xác định. Mỗi giá trị được delay trong 3 chu kỳ xung clock nên trong trường hợp của chúng ta thì giá trị là 3. Vậy sẽ delay trong 9 chu kỳ xung clock. Làm sao để biết thời gian delay là bao nhiêu? Ở trên, tôi cấu hình chip chạy với tần số 80Mhz, hàm delay giúp delay 9 chu kỳ xung clock nên nó sẽ delay trong khoảng 112.5nS. 

+ Cài đặt các chân ở chế độ Output
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1);
Phần này rất đơn giản, bạn sử dụng GPIOPinT ypeGPIOOutput(uint32_t ui32Port,uint8_t ui8Pins) để cài đặt chân thành một output. ui32Port là chân GPIO, trong trường hợp này là GPIO_PORTF_BASE. ui8Pins là chân bạn muốn cài đặt trở thành Output, trong trường hợp này là GPIO_PIN_1. Nhìn vào mạch nguyên lý của kit sẽ thấy rằng chân PF1 được kết nối tới red LED.

+ Giờ chúng ta đã có thể Blink led
Bây giờ để bật hoặc tắt LED, bạn sử dụng GPIOPinWrite(uint32_t ui32Port,uint8_t ui8Pins,uint8_t ui8Val). Biến thứ nhất và thứ 2 bạn đã biết. Biến thứ 3 là trạng thái của chân. Bạn sử dụng 0 để tắt nó, 1 để bật. Bạn cần sử dụng giá trị GPIO_PIN_x mà bạn sử dụng, ở đây là PF1.

/* 
This code was made using TivaWare 2.1.0.12573. TivaWare rights to it are all own by 
Texas Instruments 
This code shows how to blink the RED LED of the TM4C123 Launchpad using  
Tivaware. 
Luís Afonso 
*/ 
#include <stdint.h> 
#include <stdbool.h> 
#include "inc/hw_types.h" 
#include "inc/hw_gpio.h" 
#include "driverlib/pin_map.h" 
#include "driverlib/sysctl.c" 
#include "driverlib/sysctl.h" 
#include "driverlib/gpio.c" 
#include "driverlib/gpio.h" 
/* 
    This are to help if you want to change the pin you want to use so you don't 
    have to change it in the entire code 
*/ 
#define LED_PERIPH SYSCTL_PERIPH_GPIOF 
#define LED_BASE GPIO_PORTF_BASE 
#define RED_LED GPIO_PIN_1       
int main(){ 
//Set the system clock to 80Mhz 
  SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ); 
   
/* 
    Enables the clock on the GPIO, or "turns on" 
    Also, delays for a bit since it's advised in the datasheet, i add problems 
    when i didn't have that delay. 
*/ 
  SysCtlPeripheralEnable(LED_PERIPH); 
  SysCtlDelay(3); 
   
  //Set the pin of your choise to output 
  GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1); 
   
  /* 
    Here it blinks the LED with a 0.5 seconds interval. 
     
    To set a GPIO to the state HIGH you need in the third parameter to be the name 
    of the pin, ex: GPIO_PIN_1. To set to LOW just write 0. 
     
    SysCtlDelay math: 
      1/80Mhz = 12.6nS, 12,5*3= 37,5nS. 37,5*13333333=0.5 seconds 
   
  */ 
  while(1){ 
          GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_1, GPIO_PIN_1); 
          SysCtlDelay(13333333);  
          GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_1, 0); 
          SysCtlDelay(13333333); 
      } 
     


Đầu vào số đơn giản

Trong phần này tôi sẽ giải thích cách đọc giá trị đầu vào số. Đầu vào số sẽ được điều khiển bởi một nút nhấn có sẵn trên kit. Ý tưởng là bật tắt một LED khi bạn ấn nút. Nút ấn được sử dụng là SW1 được kết nối tới chân PF4.

+ Bước đầu tiên vẫn là cài đặt xung clock hệ thống, ở đây là 80Mhz

SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ);

+ Enable clock của ngoại vi

SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

+ Cài đặt nó là intput

GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_4);

Nhớ lại trong Blinky cách cài đặt một chân trở thành output. Bây giờ, đơn giản là thay GPIOPinT ypeGPIOOutput thành GPIOPinTypeGPIOInput

Chúng ta cần thêm là sử dụng điện trở nội kéo lên

GPIOPadConfigSet(GPIO_PORTF_BASE,GPIO_PIN_4,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);

Biến thứ 3 không thực sự quan trọng khi chân là một đầu vào, vấn đề là ở biến thứ 4. Cấu hình ở trên làm chân có một điện trở kéo lên. Nếu sử dụng lệnh GPIO_PIN_TYPE_STD_WPD sẽ cài đặt nó sử dụng điện trở kéo xuống. Để có nhiều thông tin hơn bạn có thể xem trong Peripheral Driver Library Guide.

+ Việc cấu hình Input đã xong. Tiếp theo, chúng ta cần cấu hình cho chân PF1 trở thành Output để có thể điều khiển LED. Các cấu hình cần thiết đã được viết ở trên, cái còn lại là cầu hình chân PF1 thành Output.

GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1);

+ Để đọc một đầu vào ta sử dụng câu lệnh sau:

GPIOPinRead(GPIO_PORTF_BASE,GPIO_PIN_4);

Thực sự là rất đơn giản để hiểu được câu lệnh này. Nó trả về một giá trị 32bit. Tại sao lại là 32bit? là vì có thể đọc toàn bộ 8 chân cùng một thời điểm nếu bạn muốn. Bit 31-8 từ gói trả về có thể được bỏ qua. Nếu chân GPIO_PIN_4 đang ở mức cao sau đó được trả về giá trị bằng với GPIO_PIN_4 (GPIO_PIN_4  được định nghĩa trong thư viện với giá trị 0x00000010). Ví dụ: Nếu đầu PF4 là 1 thì (value & GPIO_PIN_4) = GPIO_PIN_4. Nếu đầu vào là 0 thì trả về 0.

+ Bây giờ là các câu lệnh đổi trạng tại LED với button:

uint32_t value=0; 
uint8_t state=0; 
while(1){ 
    value= GPIOPinRead(GPIO_PORTF_BASE,GPIO_PIN_4); 
    if( (value & GPIO_PIN_4)==0) 
      state^=GPIO_PIN_1; 
    GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_1, state); 
    SysCtlDelay(7000000); 

Một biến được tạo để lưu trữ giá trị trả về của GPIOPinRead và sau đó kiểm tra nếu nó bằng 0 hay không. Button khi được nhấn, nó sẽ kết nối với đất nên sẽ trả về 0. Chúng ta sử dụng một biến "state" bởi vì trong GPIOPinWrite chúng ta cần để sử dụng GPIO_PIN_1 để đặt chân ở mức cao. Nên ta dùng phép XOR trạng thái với GPIO_PIN_1 để có thể lật trạng thái mỗi lần button được ấn.

Hàm Delay được gọi để delay 0.25s. Nút ấn là cơ khí, ví vậy sẽ không trả về tín hiệu 0, 1 hoàn hảo. Thay vào đó, nó sẽ chập chờn ở mức 0, 1 khi bạn nhấn trước khi thực sự ổn định.

/* 
  This code was made using TivaWare 2.1.0.12573. TivaWare rights to it are all own by 
Texas Instruments 
  This code shows how to toggle the RED LED (PF1) of the TM4C123 Launchpad 
with the left button at PF4, using Tivaware. 
  Luís Afonso 
*/ 
#include <stdint.h> 
#include <stdbool.h> 
#include "inc/hw_types.h" 
#include "inc/hw_gpio.h" 
#include "driverlib/pin_map.h" 
#include "driverlib/sysctl.c" 
#include "driverlib/sysctl.h" 
#include "driverlib/gpio.c" 
#include "driverlib/gpio.h" 
/* 
  These defines help if you want to change the LED pin or the Button pin.
  Remember if you change to a diferent GPIO you need to enable the system
  clock on it 
*/ 
#define LED_PERIPH SYSCTL_PERIPH_GPIOF 
#define LED_BASE GPIO_PORTF_BASE 
#define RED_LED GPIO_PIN_1 
#define Button_PERIPH SYSCTL_PERIPH_GPIOF 
#define ButtonBase GPIO_PORTF_BASE 
#define Button GPIO_PIN_4 
int main(void) 
  
 //Set the clock to 80Mhz 
  SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ); 
  /*
No need to enable the button peripheral since it's the same as the LED 
    in this case 
  */ 
  SysCtlPeripheralEnable(LED_PERIPH); 
  SysCtlDelay(3); 
   
  /* 
    Configure the switch on the left of the launchpad, GPIO_PIN_4 to a input with 
    internal pull‐up. 
  */ 
  GPIOPinTypeGPIOInput(ButtonBase, Button); 
  GPIOPadConfigSet(ButtonBase ,Button,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU); 
   
  /* 
    Configures the Red LED, GPIO_PIN_1, to output 
  */ 
  GPIOPinTypeGPIOOutput(LED_BASE, RED_LED); 
   
   
   
 /* 
  A variable is created to store the return value of GPIOPinRead and then checked  
 if it's 0 or not.The button when pressed, connected  the pin to the GND so it gives 0. 
  
 We use a variable "state" because in GPIOPinWrite we need to use GPIO_PIN_1 to set the pin HIGH.  
 So we XOR the state with GPIO_PIN_1 so it toggles the "state" every time the button is pressed. 
  
  The SysCtlDelay of about 0.25s is a rude way to avoid bouncing. The button being mechanical  
  doesn't give a perfect 1 and 0 signal, instead, to the "eyes" of the digital pin, it bounces 
  between 1 and 0 when you press it before stabilizing 
*/ 
  uint32_t value=0; 
  uint8_t state=0; 
  while(1){ 
    value= GPIOPinRead(ButtonBase,Button); 
    if( (value & GPIO_PIN_4)==0) 
      state^=RED_LED; 
    GPIOPinWrite(LED_BASE,RED_LED, state); 
    SysCtlDelay(7000000); 
  } 
}


Đầu vào số với NGẮT

Trong phần này tôi sẽ chỉ cho bạn cách đọc một đầu vào số sử dụng một ngắt. Sử dụng nút ấn SW1 trên kit, bật tắt để tạo một tín hiệu đầu vào. Ý tưởng là điều khiển bật tắt LED.

+ Đầu tiên là cấu hình xung clock cho hệ thống:

SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ);

+ Tiếp theo là cầu hình nút ấn và Led như 2 ví dụ phía trên.

SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); 
SysCtlDelay(3); 
   
GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_4); 
  GPIOPadConfigSet(GPIO_PORTF_BASE,GPIO_PIN_4,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU); 
   
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1); 

+ Bây giờ là ngắt.
Nếu bạn không biết một ngắt là gì? tôi khuyên bạn nên tham khảo tài liệu này. Thực sự có rất nhiều thứ để tìm hiểu đối với ngắt. Nếu bạn thực sự muốn biết về ngắt ARM-M4 bạn có thể tìm thấy ở A Beginner’s Guide on Interrupt Latency. Nhưng nói chung, việc xem xét nó cũng khá phức tạp.

Tôi hi vọng là bạn còn nhớ ở phần đầu tiên trong phần thông số kỹ thuật. IC xác định loại ngắt của GPIO có thể có:
   + Ngắt theo cạnh:
      - Cạnh lên, cạnh xuống hoặc cả hai.
     - Ngắt theo cạnh là khả năng ngắt khi một tín hiệu thay đổi từ một trạng thái này sang một trạng thái khác.
   + Ngắt theo mức:
      - Mức cao hoặc mức thấp
     - Ngắt theo mức là ngắt theo trạng thái của chân. Ví dụ: Nếu một ngắt được cấu hình là ngắt theo mức thấp thì nó sẽ gọi trình phục vụ ngắt khi chân ở trạng thái 0.

Một điều quan trọng cần chú ý là một ngắt trên GPIO. Trong TM4C123 thì mỗi GPIO có thể có duy nhất một trình phục vụ ngắt. Nghĩa là bạn không thể tạo một trình phục vụ ngắt cho riêng từng chân của GPIO. Tôi sẽ nói kỹ hơn về xử lý ngắt ở từng bit.

Vậy làm sao để cài đặt một ngắt?
Trình phục vụ ngắt là nơi được gọi và thực hiện khi một ngắt xảy ra. Tôi sẽ cho bạn thấy cách tôi sử dụng để cài đặt trình phục vụ ngắt nhưng có một cách để cài đặt nó trong file startup.c được yêu cầu bởi CCS và IAR. Cách để cài đặt nó là đầu tiên phải tạo một hàm void PortFIntHandler(). Đây là nơi mà code sẽ chạy khi một ngắt xảy ra.
Sau đó, bạn cần:
GPIOIntRegister(GPIO_PORTF_BASE,PortFIntHandler);
Bạn có thể thay đổi tên của trình phục vụ ngắt thành bất cứ tên nào bạn muốn nhưng nó cần là a void và không truyền vào tham số.

Tiếp theo, ta cần enable ngắt
GPIOIntEnable(GPIO_PORTF_BASE, GPIO_INT_PIN_4);
Bạn có thể sử dụng bất cứ nguồn kích hoạt ngắt nào dưới đây
   
    + GPIO_INT_PIN_0 ­ interrupt due to activity on Pin 0.
    + GPIO_INT_PIN_1 ­ interrupt due to activity on Pin 1.
    + GPIO_INT_PIN_2 ­ interrupt due to activity on Pin 2.
    + GPIO_INT_PIN_3 ­ interrupt due to activity on Pin 3.
    + GPIO_INT_PIN_4 ­ interrupt due to activity on Pin 4.
    + GPIO_INT_PIN_5 ­ interrupt due to activity on Pin 5.
    + GPIO_INT_PIN_6 ­ interrupt due to activity on Pin 6.
    + GPIO_INT_PIN_7 ­ interrupt due to activity on Pin 7.
    + GPIO_INT_DMA ­ interrupt due to DMA activity on this GPIO module.

Bên trong trình phục vụ ngắt:
Đầu tiên và quan trọng nhất trong một trình phục vụ ngắt là
GPIOIntClear(GPIO_PORTF_BASE, GPIO_INT_PIN_4);
Lệnh này sẽ xóa cờ ngắt. Nếu bạn không xóa nó, nó sẽ tạo một vòng lặp luôn đúng và trở lại trình phục vụ ngay khi vừa thoát khỏi. 
Chú ý rằng biến thứ 2 là cờ ngắt cần được xóa. Nhớ lại, tôi đã nói rằng mỗi GPIO chỉ có duy nhất một trình phục vụ ngắt. Nên nếu bạn muốn một ngắt trên chân 4 nhưng cũng muốn trên chân 5 thì phải làm thế nào? Bạn cần phải kiểm tra các cờ và xóa chúng.
Vậy làm sao để kiểm tra cờ nào đang được set và gọi trong trình phục ngắt? Dưới đây là ví dụ

status = GPIOIntStatus(GPIO_PORTF_BASE,true); 
GPIOIntClear(GPIO_PORTF_BASE,status); 
if( (status & GPIO_INT_PIN_4) == GPIO_INT_PIN_4){ 
  //Then there was a pin4 interrupt 
}  
if( (status & GPIO_INT_PIN_5) == GPIO_INT_PIN_5){ 
  //Then there was a pin5 interrupt 
}

Nói chung là bạn nên luôn làm điều này ngay cả khi bạn chỉ có duy nhất một ngắt được enable.

+ Bây giờ là đổi trạng thái LED
Bạn có thể sử dụng lại code của ví dụ trước nhưng với 1 khác biệt. Biến "state" cần trở thành biến toàn cục. Bởi vì giá trị của biến "state" cần được giữ lại giữ các lần ngắt và nếu nó là biến cục bộ thì điều đó sẽ không xảy ra.

volatile uint8_t value=0;
uint8_t value=0; 
value= GPIOPinRead(GPIO_PORTF_BASE,GPIO_PIN_4); 
if( value==0) 
   state^=GPIO_PIN_1; 
GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_1, state); 
SysCtlDelay(7000000);

Thực sự thì hàm delay ở đây là không cần thiết. Trong trường hợp ngày chúng ta sẽ giữ nguyên trạng thái của led bởi vì vi xử lý chỉ thực hiện delay nhưng một ngắt có thể nhanh hơn. Nó giống như một thứ gì đó chạy ngầm. Ở đây có thể có rất nhiều ngắt, vì vậy cần phải xử lý nhanh. 

Tôi hi vọng bạn sẽ thích và hiểu cách sử dụng ngắt với GPIO sử dụng TivaWare GPIO API.

Dưới đây là code:

/* 
  This code was made using TivaWare 2.1.0.12573. TivaWare rights to it are all own by 
Texas Instruments 
  This code shows how to toggle the RED LED (PF1) of the TM4C123 Launchpad 
with the left button at PF4, using Tivaware. In this one a interrupt is 
used to sense the button being pressed 
  Luís Afonso 
*/ 
#include <stdint.h> 
#include <stdbool.h> 
#include "inc/hw_types.h" 
#include "inc/hw_gpio.h" 
#include "driverlib/pin_map.h" 
#include "driverlib/sysctl.c" 
#include "driverlib/sysctl.h" 
#include "driverlib/gpio.c" 
#include "driverlib/gpio.h" 
/* 
  These defines help if you want to change the LED pin or the Button pin. 
  Remember if you change to a diferent GPIO you need to enable the system 
  clock on it

*/ 
#define LED_PERIPH SYSCTL_PERIPH_GPIOF 
#define LED_BASE GPIO_PORTF_BASE 
#define RED_LED GPIO_PIN_1 
#define Button_PERIPH SYSCTL_PERIPH_GPIOF 
#define ButtonBase GPIO_PORTF_BASE 
#define Button GPIO_PIN_4 
#define ButtonInt GPIO_INT_PIN_4 
volatile uint8_t value=0;  
void PortFIntHandler(){ 
  uint32_t status=0; 
  status = GPIOIntStatus(ButtonBase,true); 
  GPIOIntClear(ButtonBase,status); 
  if(status & ButtonInt == ButtonInt){ 
    //Then there was a Button pin interrupt 
    uint8_t value=0; 
     
    value= GPIOPinRead(GPIO_PORTF_BASE,GPIO_PIN_4); 
     
    if( value==0) 
      state^=RED_LED; 
    GPIOPinWrite(LED_BASE,RED_LED, state); 
     
    /* 
      This delay is for deboucing but since it's in a interrupt it 
      should be used a better method that is faster 
    */ 
    SysCtlDelay(7000000); 
  } 
}  
int main(void) 
  
 //Set the clock to 80Mhz 
SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ); 
  /* 
    No need to enable the button peripheral since it's the same as the LED 
    in this case 
  */ 
  SysCtlPeripheralEnable(LED_PERIPH); 
  SysCtlDelay(3); 
   
  /* 
    Configure the switch on the left of the launchpad, GPIO_PIN_4 to a input with 
    internal pull‐up. 
  */ 
  GPIOPinTypeGPIOInput(ButtonBase, Button); 
  GPIOPadConfigSet(ButtonBase ,Button,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU); 
  GPIOIntTypeSet(GPIO_PORTF_BASE,GPIO_PIN_4,GPIO_FALLING_EDGE); 
  GPIOIntRegister(GPIO_PORTF_BASE,PortFIntHandler); 
  GPIOIntEnable(GPIO_PORTF_BASE, GPIO_INT_PIN_4); 
   
  /* 
    Configures the Red LED, GPIO_PIN_1, to output 
  */ 
  GPIOPinTypeGPIOOutput(LED_BASE, RED_LED); 
   
   
   
 /* 
  A variable is created to store the return value of GPIOPinRead and then checked  
 if it's 0 or not.The button when pressed, connected  the pin to the GND so it gives 0. 
  
 We use a variable "state" because in GPIOPinWrite we need to use GPIO_PIN_1 to set the pin HIGH.  
 So we XOR the state with GPIO_PIN_1 so it toggles the "state" every time the button is pressed. 
  
  The SysCtlDelay of about 0.25s is a rude way to avoid bouncing. The button being mechanical  
  doesn't give a perfect 1 and 0 signal, instead, to the "eyes" of the digital pin, it bounces 
  between 1 and 0 when you press it before stabilizing 
*/ 
  uint32_t value=0; 
  uint8_t state=0; 
  while(1){ 
    value= GPIOPinRead(ButtonBase,Button); 
    if( value==0) 
      state^=RED_LED; 
    GPIOPinWrite(LED_BASE,RED_LED, state); 
    SysCtlDelay(7000000); 
  }


Ví dụ về điều khiển màu sắc bóng đèn RGB

Trong phần này tôi chỉ nêu ra code chứ không giải thích bởi qua các ví dụ phía trên bạn đã hiểu rất rõ về GPIO. Nên ở ví dụ này, giải thích là không cần thiết nữa. Ở ví dụ này, chúng ta sẽ tìm hiểu cách kết hợp bật tắt các led có trên led RGB để thay đổi màu sắc.
Tham khảo user guide để thấy rõ hơn cách kết nối các chân.

Dưới đây là code:

/* 
   
  Example code made using IAR workbench with TivaWare for the Tiva TM4C123 launchpad 
  It's an example with simple digital output and inputs. When you press the left button 
on the launchpad it cycles the combinations of colors of a RGB LED. 
  
  red‐>purple‐>blue‐>light blue‐>green‐>yellow‐>red, and back to purple. 
  Luís Afonso 
*/ 
#include <stdint.h> 
#include <stdbool.h> 
#include "inc/hw_types.h" 
#include "inc/hw_gpio.h" 
#include "driverlib/pin_map.h" 
#include "driverlib/sysctl.c" 
#include "driverlib/sysctl.h" 
#include "driverlib/gpio.c" 
#include "driverlib/gpio.h" 
#define LEDbase GPIO_PORTF_BASE 
#define LEDred GPIO_PIN_1 
#define LEDblue GPIO_PIN_2 
#define LEDgreen GPIO_PIN_3 
int main(){ 
   
  SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); 
  SysCtlDelay(3); 
   
  GPIOPinTypeGPIOOutput(LEDbase, LEDred|LEDblue|LEDgreen); 
  
  GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_4); 
  GPIOPadConfigSet(GPIO_PORTF_BASE,GPIO_PIN_4,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU); 
   
  uint32_t value =  GPIOPinRead(GPIO_PORTF_BASE,GPIO_PIN_4); 
   
   //================Turn on red=======================    
          GPIOPinWrite(LEDbase,LEDred, LEDred); 
           
          //Wait for a button press 
         do{ 
            value =  GPIOPinRead(GPIO_PORTF_BASE,GPIO_PIN_4); 
          } while ((value&GPIO_PIN_4)!=0); 
         //Wait for the button to be let go 
         do{ 
            value =  GPIOPinRead(GPIO_PORTF_BASE,GPIO_PIN_4); 
          } while ((value&GPIO_PIN_4)==0); 
  //=======================================    
     
     
    while(1){ 
       
      //==================Get purple color======================= 
      //======================Turn on blue=================      
          GPIOPinWrite(LEDbase,LEDblue, LEDblue); 
         do{ 
            value =  GPIOPinRead(GPIO_PORTF_BASE,GPIO_PIN_4); 
          } while ((value&GPIO_PIN_4)!=0); 
         do{ 
            value =  GPIOPinRead(GPIO_PORTF_BASE,GPIO_PIN_4); 
          } while ((value&GPIO_PIN_4)==0);  
     //====================================================  
          
             
     //=================Get blue color==========================        
     //======================Turn off red=================    
          GPIOPinWrite(LEDbase,LEDred, 0); 
          do{ 
            value =  GPIOPinRead(GPIO_PORTF_BASE,GPIO_PIN_4); 
          } while ((value&GPIO_PIN_4)!=0); 
         do{ 
            value =  GPIOPinRead(GPIO_PORTF_BASE,GPIO_PIN_4); 
          } while ((value&GPIO_PIN_4)==0);  
     //=================================================== 
          
             
    //====================Get light blue color================== 
//========================Turn on green===============      
          GPIOPinWrite(LEDbase,LEDgreen, LEDgreen); 
          do{ 
            value =  GPIOPinRead(GPIO_PORTF_BASE,GPIO_PIN_4); 
          } while ((value&GPIO_PIN_4)!=0); 
         do{ 
            value =  GPIOPinRead(GPIO_PORTF_BASE,GPIO_PIN_4); 
          } while ((value&GPIO_PIN_4)==0);  
     //====================================================  
             
      
     //=====================Get green color================ 
     //======================Turn off blue=================    
          GPIOPinWrite(LEDbase,LEDblue, 0); 
          do{ 
            value =  GPIOPinRead(GPIO_PORTF_BASE,GPIO_PIN_4); 
          } while ((value&GPIO_PIN_4)!=0); 
         do{ 
            value =  GPIOPinRead(GPIO_PORTF_BASE,GPIO_PIN_4); 
          } while ((value&GPIO_PIN_4)==0);  
     //====================================================        
        
          
     //===============Get yellow color=================== 
     //================Turn on Red=======================    
            GPIOPinWrite(LEDbase,LEDred, LEDred); 
            do{ 
              value =  GPIOPinRead(GPIO_PORTF_BASE,GPIO_PIN_4); 
            } while ((value&GPIO_PIN_4)!=0); 
         do{ 
            value =  GPIOPinRead(GPIO_PORTF_BASE,GPIO_PIN_4); 
          } while ((value&GPIO_PIN_4)==0);  
    //==================================================== 
          
          
      //====================Get red color===================       
      //======================Turn off green=================    
          GPIOPinWrite(LEDbase,LEDgreen, 0); 
          do{ 
            value =  GPIOPinRead(GPIO_PORTF_BASE,GPIO_PIN_4); 
          } while ((value&GPIO_PIN_4)!=0); 
         do{ 
            value =  GPIOPinRead(GPIO_PORTF_BASE,GPIO_PIN_4); 
          } while ((value&GPIO_PIN_4)==0);  
     //======================================================           
      } 
   

The End: I hope you can understand what i want to show you throught this tutorial. And i also hope you can join me for the next tutorial. The next tutorial will talk about How to use ADC TM4C123 with TivaWare. Goodbye!!!

1 nhận xét: