Starting Electronics needs your help! Please make a donation to help cover our hosting and other costs. Click the donate button to send a donation of any amount.
Created on: 3 June 2016
Part 9 of the ASF ARM Tutorial
How to write to a port or group of pins on an Atmel ARM Cortex microcontroller using ASF in Atmel Studio.
So far in this tutorial series we have looked at how to enable single microcontroller pins as outputs. ASF has functions that can be used to write to an entire port or to selected pins on a port using a mask to select the pins.
In this part of the ASF ARM tutorial four consecutive pins on a port are configured as outputs and LEDs are connected to them. A count value is written to the LEDs by calling an ASF module function.
The following ASF IOPORT module functions are used to configure and write to the port:
Code is run on an Atmel SAM4N Xplained Pro board and four LEDs with series resistors are connected to PORTA pins on the EXT1 connector as shown in the image below. If you are using a different board, make the necessary changes to your hardware and software if needed.
Pins from the 20-pin EXT1 header are connected to the breadboard using a flat ribbon cable with two female IDC connectors and single core jumper wires.
The following pins are used on the pin header:
Each of the four pins is connected to the anode of its own LED and 470Ω series resistor. The other side of each series resistor connects back to the common GND rail on the breadboard. In other words the LEDs are wired in a current sourcing configuration.
Create a new ASF project called out_port in Atmel Studio as explained in the ASF quick start checklist.
Add the IOPORT - General purpose I/O service (service) module and the Delay routines (service) module to the project using the ASF Wizard. The System Clock Control service module does not have to be added as it is a dependency of the IOPORT module and so is added automatically as shown in the image from the ASF Wizard below. Expanding the IOPORT module in ASF Wizard reveals that it is dependent on the System Clock Control module. It therefore does not matter if you add this module or not.
The application is written by modifying the following files in the out_port Atmel Studio project.
Hardware for the board is defined in conf_board.h as shown below. A mask value for the four LEDs is defined and an offset value to shift the mask to the correct position on the port.
\src\config\conf_board.h
#ifndef CONF_BOARD_H #define CONF_BOARD_H // 4 LEDs on pins PA11, PA12, PA13 and PA14 // LEDs starting at pin 11 of PORTA #define EXT_LED_PORTA_OFFSET 11 // 4 bit wide mask for LEDs on PORTA #define EXT_LED_PORTA_MASK (0x0F << EXT_LED_PORTA_OFFSET) // clock resonators #define BOARD_FREQ_SLCK_XTAL (32768U) #define BOARD_FREQ_SLCK_BYPASS (32768U) #define BOARD_FREQ_MAINCK_XTAL (12000000U) #define BOARD_FREQ_MAINCK_BYPASS (12000000U) #define BOARD_MCK CHIP_FREQ_CPU_MAX #define BOARD_OSC_STARTUP_US 15625 #endif // CONF_BOARD_H
Hardware initialization functions are called in board_init() which is found in the init.c file.
\src\ASF\common\boards\user_board\init.c
#include <asf.h> #include <board.h> #include <conf_board.h> void board_init(void) { WDT->WDT_MR = WDT_MR_WDDIS; // disable watchdog ioport_init(); // call before using IOPORT service // enable PORTA and set direction of port as output ioport_enable_port(IOPORT_PIOA, EXT_LED_PORTA_MASK); ioport_set_port_dir(IOPORT_PIOA, EXT_LED_PORTA_MASK, IOPORT_DIR_OUTPUT); }
ioport_enable_port() is called to enable the selected port. In this case PORTA or PIOA is enabled by passing IOPORT_PIOA as the first parameter to this function. The LED mask for the four LEDs defined in conf_board.h is passed as the second parameter to this function.
ioport_set_port_dir() is called to set the direction of the selected port. The port name is passed as the first parameter and the LED mask value as the second parameter. IOPORT_DIR_OUTPUT, the third parameter passed to this function, sets the masked LED pins as outputs on the selected port.
Finally the main application code can be added to main.c. The application listed below simply writes a count to the four LEDs. Because the LEDs are not connected to the bottom four pins of the port, the count must be shifted up to the LEDs on the port.
\src\main.c
#include <asf.h> int main (void) { uint32_t count = 0; sysclk_init(); board_init(); while (1) { ioport_set_port_level(IOPORT_PIOA, EXT_LED_PORTA_MASK, (count << EXT_LED_PORTA_OFFSET)); count++; delay_ms(200); } }
ioport_set_port_level() takes the port name as the first parameter, LED or pin mask as the second parameter and the shifted count value as the third parameter. When this function is called, it displays the bottom four bits of the count on the LEDs.
The following video shows the code running on the SAM4N Xplained Pro board.
Can't see the video? View on YouTube →
As an Amazon Associate I earn from qualifying purchases: