EnSol AS R&D and prototyping expertise.
© EnSol AS 2019
Technical Blog

Technical Blog

Specialised R&D equipment is expensive, usually takes many months to arrive, has to be interfaced with, and never quite does what you want it to do! The aim of this blog is to share a few hints and tips on some of the items of equipment and tools we at EnSol have used, and custom built as part of our own R&D work. Please have a look below: Qartz Deposition Rate Monitor AVR-32: o Powering up and Getting Started With Ports. o Serial Communications With the USART. o Using the ADC and outputting the data to USART. o Using a timer- A simple time delay.

Quartz Deposition Rate Monitor

One great asset in a deposition system is a deposition rate monitor. This is crystal of quartz that is set to resonate at its natural frequency. As material is deposited onto the crystal, this frequency changes, and from the rate of frequency change, a deposition rate can be calculated. In many cases even a relative deposition rate is of great use; to identify if a rate has dropped off after a deposition cycle for example, or simply if there is any beam there! For the rate monitoring specialist crystals are commonly available for around $3 per piece (see figure). They consist of a thin slab of a single quartz crystal with (typically) gold or silver contacts on front and back. The challenge with operating the crystals is that the front (solid contact) surface is usually in contact with a metal crystal holder and grounded to the rest of the deposition system. This avoids any build-up of charge on the surface when used in sputter systems for example, but makes the electronics of any oscillator more complicated.

The Oscillator Circuit

The figure shows a simple free-running crystal-driver circuit based on the MC100EL16 or MC10H116 differential line driver ICs. The sine wave output from the drivers are converted to a TTL square wave, via a TLV3501 high- speed comparator, for subsequent processing.

Counting the Pulses

To calculate a deposition rate, the frequency change over time must be measured. The simplest way of doing this is to just count the number of oscillations per second. However, for low density materials and low deposition rates, the frequency change that needs to be measured can be less than 1Hz, which can ultimately lead to long measurement times. To slightly speed this process up, an alternative is to “gate” a second higher speed counter with a certain number of pulses from the crystal. Such a circuit is shown in the figure to the right. The 74LV8154 IC’s are both used in 32-bit (4-byte) counting mode. The first IC is set to count, and transfer the counts to the output buffer, with every incoming crystal pulse. It is set up to output the 3rd byte of data on its outputs. A set of jumpers allows a particular counter bit to be selected e.g. for the 22nd bit corresponding to 4,194,304 counts - which will clock in less than 1 second with a 6MHz crystal. A second 74LV8154 IC is implemented and clocked from an active oscillator module. (In this case 30Mhz - 5 times the crystal frequency). Counts from this counter however, are only transferred to the output buffer when an incoming pulse is received from the first 74LV8154 IC. The result gives; the number of 30MHz pulses in every 4,194,304 crystal oscillations, from which the crystal frequency can be calculated - but at 5 times the speed of counting the crystal pulses directly. The second counter can simply be left running and software used to determine when the counter has rolled-over (and started from zero again). Interfacing to the two counters is done with an Atmel AVR-8 (atmega-168) microcontroller. This does the basic housekeeping for the timers, resetting them, collecting the bytes of data and sending them to wherever they are needed. In our case, they are transmitted via a simple RS-485 interface to a computer which controls the whole vacuum system, where the deposition rate can be calculated and plotted. The figure to the right shows the final oscillator and counter module with microcontroller. (The RJ-45 connector is used as a cost effective interface for supplying power and RS-485 connections, allowing several units to be daisy chained together)

The Mechanics

A considerable expense with installing a deposition rate monitor is the mechanics; the crystal housing, wiring and electrical feed-through into the vacuum system. One great draw-back is that water cooling is often implemented to prevent any shift in the crystal frequency as a result of temperature change. (This is particularly the case when it is desirable to move the deposition rate monitor in and out of a beam). For thermal deposition systems, this temperature variation may be a significant source of error (typically of the order of 1ppm / oC). Compensation systems, such as temperature monitoring, or using a hidden reference crystal could be implemented as an alternative to the water cooling, but if the likely thermal drift is acceptable, then the whole system can be made much more flexible and simple, without compensation or water pipes. (Increasing the “thermal mass” of the crystal holder can also be used to help reduce the effect where only intermittent rate checking is needed). The first two figures show a simple deposition monitor housing. Small, plated, spring loaded “pogo-pins” are used to hold the crystal in place and provide electrical connection to the back of the crystal. A printed circuit board, allows for a very cost effective way of providing an electrical connection, in this case through an MCX connector . (Though not ideal for Ultra High Vacuum (UHV) systems, the component outgassing rate has been found insignificant for our own HV system particularly when used in conjunction with lead free solder.) Finally for connecting the crystal through the vacuum chamber and to the outside world, today’s large selection of small RF connectors are idea for the application. The insulators of such connectors are usually PTFE and whilst it’s doubtful that the metal parts are gold plated and not simply titanium nitride coated, they are equally compatible with a vacuum system. The last figure shows a few such connectors, the threaded SMA style to the left and the smaller MCX to the right. Smaller cables and connectors are available, but the ones shown, area a nice size to use, being compact and space saving but not too fiddly. For the cable connectors the “windowed” style is highly recommended. These have the central pins moulded in-place and the central wire can be soldered directly to it via an access window in the connector housing. So there is no trouble with having to cut the various cores to precise lengths and insert the central pin afterwards. To the rear of the photo a length of RG-316 cable is shown, which is used in conjunction with these connectors. This can be purchased with silver plated wire, and PTFE or FEP insulator (around $1 /m). In some cases, to minimise virtual leaks, the outer jacket of the cable can be removed, however this does adversely effect the flexibility of the cable and has been found unnecessary in our own vacuum system.

AVR-32:

Atmel’s 32-Bit UC3C Microcontrollers:

Atmel’s AVR-32 series of microcontrollers offers a tremendous increase in power and flexibility over its AVR- 8 (8-bit) controllers, but there is little information available on the net about them. Atmel does have extensive documentation with its AVR-32 framework files, but this can be a little hard to get into, and not very easy to understand what’s actually going on. Most of the examples also tend to be specific for a particular demonstration board, so it can be a bit of a leap in at the deep end developing your own application. These pages are aimed at helping making the transition.

Basic connections:

For ease of availability and soldering I have chosen the 32UC3C264C-U controller. To make sure you have all the connections needed for your application for these UC3 C devices Atmel does have the handy AVR32768 application note with schematic check-list. The schematic (opposite) shows the very basic connection for powering, programming and de-bugging. (With an additional 3 LEDs connected for demonstrating the port functions.) For my own testing I am using a JTAGICE MKII with AVR visual studio 6.2. I found that version 6.0 had a few bugs in it like not showing up some of the ports when debugging.

Getting to grips with the ports:

The first important information you need from the data sheet is found in section 3.2.1 table 3-1 (page 11) which shows the various pin functions and allocations on the controller (an extract is shown opposite).We can see pin 42 (PC18) is linked to General-Purpous Input/Output - GPIO number 82. Like the 8-Bit controllers the AVR-32 also have a series of different ports, with associated (32-bit) registers to allow access to them. However the various Port C, Port D.. etc are not as strictly defined. So the correct GPIO port number is calculated by dividing the GPIO number by 32 (and rounding down). GPIO Port Number = floor (82/32) = 2 The corresponding GPIO pin number is now calculated as the remainder of the GPIO number divided by 32: GPIO Pin Number = remainder (82/32) = 18 (See page 461 of the data sheet for more information.) Now we know which pins we are dealing with we need to set them to outputs and switch them. There are several different commands available for switching the GPIO functions: (S)et - Sets a particular pin or pins to 1. (C)lear - Sets a particular pin or pins to 0. (T)oggle- Toggles / cycles a particular pin or pins 0, 1, 0, 1 etc. (And the direct command without suffix which sets all the pin values.) Firstly we need to enable the particular pins using the GP Enable Register command, in this case we use the Set command gpers: As the commands are typed into Atmel studio the auto-complete function will assist with finding the correct commands. The statement is interpreted as; using the AV32_GPIO functions, working on port [2], using GPIO (set) enable register, and writing a 1 to bit No. 17 (ie. 1 left shifted 17 places). Next we need to set the pins as outputs, by enabling the pin drive function with the Ouput Driver Enable Set command: Finally we’re ready to switch the LEDs off and on. This is done using the OVR command, to set all the pins directly or using Set, Clear and Toggle options for only changing a particular pin (in a similar way to the sbi and cbi functions used with AVR-8 programming. (See page 461 of the data sheet for more information.) So we can now put together a simple program to sequentially light the LEDs. (Note the AVR-32 does not support the _delay_ms() function of the AVR-8 so the LEDs will flash rather quickly!!

Serial Communications with the USART:

Again whilst the AVR-32 framework offers examples of using the USART they are not so transparent and easy to configure for your own use. This section will demonstrate how to set up the USART to send characters. These can be picked up on a computer using a “com-port” viewer such as “RealTerm” using a simple “USB TTL RS-232” interface which can be purchased very cheaply from china. A schematic for wiring up the microcontroller is shown opposite. Ports PC16 (and PC15) will be used for the USART. This choice is made with reference to section 3.2.1 table 3-1 (page 11) of the data sheet shown opposite. We see these chosen pins can be used as USART0-TXD & USART0-RXD if we select GPIO function D. The first thing that must be done with the microcontroller is to change the system clock, as by default this is set to RCSYS which is 115kHz, (see page 60 of the data sheet), and is a little slow for useful baud rates of serial communication. For convince we will switch to the built in 8MHz system clock. Before we can switch the main system clock to the internal 8MHz clock it first has to be enabled. This is done with the RCR8 register, which is part of the System Control InterFace module (page 114). The 8MHz clock is calibrated at start-up, in order to preserve this calibration value we will first copy it to a variable before rewriting it, with the enable bit, to the register. This register is protected by a lock however, and in order to unlock the register, to make changes to it, we have to write both a key (0xAA) and the address offset of the RCR8 register (0x0048) to the SCIF UNLOCK register (page 100). Again the auto-complete function of AVR studio is a great help, and has values for these already implemented. (The actual value of the auto complete AVR32_SCIF_UNLOCK_KEY_VALUE variable is shown as it is selected. Placing the cursor on this text brings up its defined value at the top of the code window.) Having unlocked the RCR8 register we can now write to it and enable the clock: Once activated and running, we can now switch the main system clock over, using the Main Clock ConTRoL registers in the Power Manager module (page 60). Again this register is lock protected: Having unlocked the MCCTRL register we can now write to switch over the clock source: Next comes the job of setting up the TX output pin. Firstly we switch the PC16 port pin to peripheral mode by clearing the corresponding GPIO bit (page 462). This allows the pin to be used by one of the other peripheral functions of the port: From the GPIO function table (show at the start of this section) we can see that function D is for using this pin as USART0 TX. This is selected by programming the corresponding Peripheral Mux Registers in the GPIO module for that pin. For Peripheral function D we need to set PMR2, PMR1, PMR0 to 011 (see page 267). We can now initialise USART0. In this case we will set it up in simple asynchronous mode, 8-bits, no parity, 38,400 Baud. The first of these parameters are set using the Mode Register of the USART module. All bits in this register are reset to zero at start-up as shown in table 25-16 page 625 so only the following need to be changed: Next the correct Baud rate for an 8MHz clock is set using the Baud Rate Generation Register and changing the Clock Divider bits to 13 (see page 569): We can now activate the transmit function using the TX ENable bits of the USART Control Register (page 626): The USART is now set up and ready to transmit data by writing a character to the TX CHARacter bits of the Transmitter Holding Register. An additional while loop can be used for when transmitting many characters to delay until the Transmitter Holding Register is again empty (page 635). The completed program now looks like this: [Comment - 04/18 it seems the added while loop does not actually cause any delay once complied!!]
Basic connections for 32UC3C3264 microcontroller.
GPIO Port, Pin & Function Allocation.
Basic USART connections for 32UC3C3264 microcontroller.

Using the ADC and outputting the data to the USART:

In this section we will set up the ADC of the microcontroller to do a simple single conversion and then send the value to the USART (after converting it to an Ascii character string).

Initialising the ADC:

If you have run through the previous sections in this AVR-32 blog, you should be feeling more confident with accessing the various registers and functions of the 32-bit microcontrollers. So we can launch straight in with the initialisation of the ADC: The code itself is fairly self explanatory. The ADC section of the data sheet gives more information about the registers used. It’s worth noting the reset values of the various registers (typically zero), and what functions are set up by default as a result. This allows only the bare minimum of register changes to be set. A couple of notes regarding the auto-complete function, which tend to cause a few compiling errors if not spotted: Be very aware that something like: AVR32_ADCIFA_INNSEL00_CNV0 is actually a defined value where as: AVR32_ADCIFA.INPSEL00.cnv0 refers to a section of a register. Similarly: AVR32_ADCIFA.innsel00 refers to the whole value of the register (and is expected to be followed by =[value]; where as: AVR32_ADCIFA.INNSEL00 refers to part of a register (and is expected to be followed by which part you wish to address e.g. .cnv0)

Converting a number to a string of characters:

One useful routine to have around is for converting a number to a string of Ascii characters that can easily be viewed on something like RealTerm com-port viewer (after sending over the USART). To avoid complicating the routine with pointers, the variables ADC and Sign are made public in the initial part of the code.

Full ADC to character string code:

The code shown below combines the above sections with the previously introduced code. The 10-bit ADC value from differential inputs on pins PA4 and PA19 and continuously sent as a character string. The main routine: Signals for the start of a new ADC conversion, and then waits for it to complete. Copies the value to a variable and sends this to be converted into a character string. This is then sent over the USART before resetting the ADC end of sequence flag. A couple of notes on the code: AVR studio in its many guises often has issues with returning actual values from variables in debugging mode. In this case the variable ADC_Value could be stated as an integer however when debugging it always has the value of zero. Forcing the variable to be a volatile solves this problem, and the value can be check. However it was found that the value would not be updated properly if the code was interrupted each ADC cycle, only if the code was allowed to proceeded and then paused after some interval. The subroutine Send_Serial could use a simple loop to send each character of the string to the USART. However from experience with AVR-8 microcontrollers, this can sometimes lead to loss of data as the loop takes too much controller processing time and the synchronisation of the serial data is lost. “Carriage return” and “line feed” characters are added to the end of the data. This formats the data nicely in the com-port viewer, returning placing the cursor to the start of the next line.

A Simple Timer routine:

Accessing the timer / counters on the AVR-32 chips is a little harder than you might expect, as finding the actual registers in the AVR studio software takes a fair bit of trial and error! The simple routine shown below initialises Timer0 and programs the Compare register of part A of this timer. A simple while loop is included for illustration, which waits for a compare match before exiting the loop. An LED previously set up, (on port PC18) is toggled with each cycle to allow the execution to be verified. In this case the timer is reset by the software with each cycle, rather than using it in continuous wave mode, as it is the ultimate intention to use this timer a simple one-shot time delay. Note that the clock source is selected to be TIMER_CLOCK2 (see page 850) which according to page 869 is PBC clock / 2 and more details of this clock are found in the Power Management section of the data sheet. By default PBC clock runs at the main system clock frequency (see page 63). (See the USART section of this blog on how to change the system clock settings). One thing to note with the timers is that each Timer actually has 3 channels A, B & C although only A & B can access input & output pins.) .
AVR32_GPIO.port[2].gpers=1<<17; // Activate GPIO number 81 - PC17 AVR32_GPIO.port[2].gpers=1<<18; // Activate GPIO number 82 - PC18 AVR32_GPIO.port[2].gpers=1<<19; // Activate GPIO number 83 - PC19
AVR32_GPIO.port[2].oders=1<<17; // Enable output driver GPIO number 81 AVR32_GPIO.port[2].oders=1<<18; // Enable output driver GPIO number 82 AVR32_GPIO.port[2].oders=1<<19; // Enable output driver GPIO number 83
AVR32_GPIO.port[2].ovr=1 <<17; // Drive Pin 41 GPIO number 81 high (all other pins low) AVR32_GPIO.port[2].ovc=1 <<17; // Drive Pin 41 GPIO number 81 low AVR32_GPIO.port[2].ovs=1 <<17; // Drive Pin 41 GPIO number 81 high AVR32_GPIO.port[2].ovt=1 <<17; // Toggle Pin 41 GPIO number 81 high
#include <avr32/io.h> unsigned int i; int main(void) { AVR32_GPIO.port[2].gpers=1<<17; // Activate GPIO number 81 - PC17 AVR32_GPIO.port[2].gpers=1<<18; // Activate GPIO number 82 - PC18 AVR32_GPIO.port[2].gpers=1<<19; // Activate GPIO number 83 - PC19 AVR32_GPIO.port[2].oders=1<<17; // Enable output driver GPIO number 81 AVR32_GPIO.port[2].oders=1<<18; // Enable output driver GPIO number 82 AVR32_GPIO.port[2].oders=1<<19; // Enable output driver GPIO number 83 while (1) { AVR32_GPIO.port[2].ovr=1 <<16; //Set Pin i=0; while (i<10000) { i=i+1; } AVR32_GPIO.port[2].ovr=1 <<17; //Set Pin i=0; while (i<10000) { i=i+1; } AVR32_GPIO.port[2].ovr=1 <<18; //Set Pin i=0; while (i<10000) { i=i+1; } } }
unsigned char CalibrationValue; CalibrationValue=AVR32_SCIF.RCCR8.calib;  // Store 8MHz Calibration value AVR32_SCIF.unlock=((AVR32_SCIF_UNLOCK_KEY_VALUE << AVR32_SCIF_UNLOCK_KEY_OFFSET) | AVR32_SCIF_RCCR8);   // Unlock the register to allow a change to be made AVR32_SCIF.rccr8=((1 << AVR32_SCIF_RCCR8_RCOSC8_EN_OFFSET)  | CalibrationValue); // Enable 8MHZ clock with original calibration AVR32_PM.unlock=((AVR32_PM_UNLOCK_KEY_VALUE << AVR32_PM_UNLOCK_KEY_OFFSET) | AVR32_PM_MCCTRL_MCSEL_OFFSET);	// Unlock the PM register to allow a change of clock source AVR32_PM.mcctrl=AVR32_PM_MCCTRL_MCSEL_RCOSC8; // Select internal 8MHz main clock AVR32_GPIO.port[2].gperc=1<<16; // Set to peripheral mode (clear bit) AVR32_GPIO.port[2].pmr0s=1<<16;	// Set	 	AVR32_GPIO.port[2].pmr1s=1<<16;	// Set 	AVR32_GPIO.port[2].pmr2c=1<<16; 	// Clear AVR32_USART0.MR.usart_mode.par=0b100; 	// No Parity  	AVR32_USART0.MR.usart_mode.chrl=0b11; 	// 8 Data Bits AVR32_USART0.BRGR.cd=13; // Set Baud Rate to 38400 @ 8MHz AVR32_USART0.CR.usart_mode.txen=1; // Activate transmitter AVR32_USART0.THR.txchr=’!’; // Send ! character 	while ( !(AVR32_USART0.CSR.usart_mode.txrdy & 1) ) { 		; 								// wait here until buffer empties 	}
#include <avr32/io.h> void Initialise_USART(void); unsigned int i; int main(void) { Initialise_USART(); while(1) { AVR32_USART0.THR.txchr='!'; // Send ! character while (!(AVR32_USART0.CSR.usart_mode.txrdy & 0b1)) { ; // wait here until buffer empties } i=0; while (i<90000) { i=i+1; } } } //========================================================================= void Initialise_USART(void){ // Initialise the USART for serial comms // For 384OO baud CD is 13 @ 8MHz 20 @12 MHz // TX is on USART0 PC16 - GPIO 80 = port 2 pin 16 unsigned char CalibrationValue; // Initialise 8MHZ system clock CalibrationValue=AVR32_SCIF.RCCR8.calib; // Store 8MHz Calibration value AVR32_SCIF.unlock=((AVR32_SCIF_UNLOCK_KEY_VALUE << AVR32_SCIF_UNLOCK_KEY_OFFSET) | AVR32_SCIF_RCCR8);// Unlock the register to allow a change to be made AVR32_SCIF.rccr8=((1 << AVR32_SCIF_RCCR8_RCOSC8_EN_OFFSET) | CalibrationValue); // Enable 8MHZ clock with original calibration AVR32_PM.unlock=((AVR32_PM_UNLOCK_KEY_VALUE << AVR32_PM_UNLOCK_KEY_OFFSET) | AVR32_PM_MCCTRL_MCSEL_OFFSET);// Unlock the PM register to allow a change of clock source AVR32_PM.mcctrl=AVR32_PM_MCCTRL_MCSEL_RCOSC8; // Select internal 8MHz main clock (see p 60) // Set up the GPIO registers - Peripheral interface D with AVR32_GPIO.port[2].gperc=1<<16; // Set to peripheral mode (clear bit) // Set PMR2,PMR1,PMR0 to 011 -D for the mux GPIO register see page 468 AVR32_GPIO.port[2].pmr0s=1<<16;// Set AVR32_GPIO.port[2].pmr1s=1<<16;// Set AVR32_GPIO.port[2].pmr2c=1<<16; // Clear // Program USART0 (all bits set to 0 on reset) AVR32_USART0.MR.usart_mode.par=0b100; // No Parity AVR32_USART0.MR.usart_mode.chrl=0b11; // 8 Data Bits AVR32_USART0.BRGR.cd=13; // Set Baud Rate to 38400 @ 8MHz AVR32_USART0.CR.usart_mode.txen=1; // Activate transmitter } //=========================================================================
void Initialise_ADC(void){ // Initialise the ADC // Active Pins PA4(ADCIN0+) and PA19(ADCIN8-) GPIO= 4 & 19 (port 0) function A // Set up the GPIO registers AVR32_GPIO.port[0].gperc=1<<4; // Set to peripheral mode AVR32_GPIO.port[0].gperc=1<<19; // Set to peripheral mode AVR32_GPIO.port[0].puerc=1<<4; // Clear pull-up AVR32_GPIO.port[0].puerc=1<<19; // Clear pull-up // Set PMR2,PMR1,PMR0 to 000 -A AVR32_GPIO.port[0].pmr0c=1<<4; AVR32_GPIO.port[0].pmr1c=1<<4; AVR32_GPIO.port[0].pmr2c=1<<4; // select function A for the mux GPIO register see page 468 AVR32_GPIO.port[0].pmr0c=1<<19; AVR32_GPIO.port[0].pmr1c=1<<19; AVR32_GPIO.port[0].pmr2c=1<<19; // select function A for the mux GPIO register see page 468 //.............. AVR32_ADCIFA.CFG.adcen=0; // Ensure ADC is disabled before setting AVR32_ADCIFA.CFG.shd=1; // No sample and hold (no gain control) AVR32_ADCIFA.CFG.rs=1; // Use 0.6xVDDANA as reference voltage AVR32_ADCIFA.CFG.ssmq=1; // Single sequence mode AVR32_ADCIFA.SEQCFG0.cnvnb=0; // Do 1 conversion only AVR32_ADCIFA.SEQCFG0.sres=1; // 10 bit accuracy AVR32_ADCIFA.ckdiv=3; // Set the clock divide by to 3 to get from 8MHz to <1.5MHz AVR32_ADCIFA.INPSEL00.cnv0=0; // Set Positive pin to ADCIN0 AVR32_ADCIFA.INNSEL00.cnv0=0; // Set Negative pin to ADCIN8 (see page 1147) AVR32_ADCIFA.CFG.adcen=1; // Enable ADC }
void Int_To_Ascii(int X){ // Converts a signed integer number into an Ascii array unsigned int Y,Th,T,U,H; Sign='+'; Y=X; if (X < 0) { Y=(!X+1); // Effectively 'two's complement - converts to an unsigned value plus sign Sign='-'; } Th=Y/1000; // Calculate the whole number of Thousands, Hundreds, Tens and Units H=Y/100-Th*10; T=Y/10-Th*100-H*10; U=Y-T*10-H*100-Th*1000; ADC[0]=U+48; // Add 48 to the Value to convert it to the correct character and allocate to array ADC[1]=T+48; ADC[2]=H+48; ADC[3]=Th+48; }
#include <avr32/io.h> void Initialise_USART(void); void Initialise_ADC(void); void Int_To_Ascii(int X); void Send_Serial(void); unsigned long i, j; volatile ADC_Value; // Defaults to integer but will not return a value in debug mode if not set to volatile. // Note also value does not update in debug mode, program must be run and stopped to see any change unsigned char Sign, ADC[3]; // Variables used to hold the Ascii string for the ADC Value int main(void) { Initialise_USART(); Initialise_ADC(); while(1) { AVR32_ADCIFA.CR.soc0=1; // Start sequence 0 conversion while (!(AVR32_ADCIFA.SR.seos0 & 0b1)) { ; // wait here until sequence is completed see page 1124 } ADC_Value=AVR32_ADCIFA.resx[0]; Int_To_Ascii(ADC_Value); // Convert the number to an Ascii String Send_Serial(); // Send the characters over the serial coms. AVR32_ADCIFA.SCR.seos0=1; // Clear the end of sequence flag } } //========================================================================= void Initialise_USART(void){ // Initialise the USART for serial comms // For 384OO baud CD is 13 @ 8MHz 20 @12 MHz // TX is on USART0 PC16 - GPIO 80 = port 2 pin 16 unsigned char CalibrationValue; // Initialise 8MHZ system clock CalibrationValue=AVR32_SCIF.RCCR8.calib; // Store 8MHz Calibration value AVR32_SCIF.unlock=((AVR32_SCIF_UNLOCK_KEY_VALUE << AVR32_SCIF_UNLOCK_KEY_OFFSET) | AVR32_SCIF_RCCR8);// Unlock the register to allow a change to be made AVR32_SCIF.rccr8=((1 << AVR32_SCIF_RCCR8_RCOSC8_EN_OFFSET) | CalibrationValue); // Enable 8MHZ clock with original calibration AVR32_PM.unlock=((AVR32_PM_UNLOCK_KEY_VALUE << AVR32_PM_UNLOCK_KEY_OFFSET) | AVR32_PM_MCCTRL_MCSEL_OFFSET);// Unlock the PM register to allow a change of clock source AVR32_PM.mcctrl=AVR32_PM_MCCTRL_MCSEL_RCOSC8; // Select internal 8MHz main clock (see p 60) // Set up the GPIO registers - Peripheral interface D with AVR32_GPIO.port[2].gperc=1<<16; // Set to peripheral mode (clear bit) // Set PMR2,PMR1,PMR0 to 011 -D for the mux GPIO register see page 468 AVR32_GPIO.port[2].pmr0s=1<<16; // Set AVR32_GPIO.port[2].pmr1s=1<<16; // Set AVR32_GPIO.port[2].pmr2c=1<<16; // Clear // Program USART0 (all bits set to 0 on reset) AVR32_USART0.MR.usart_mode.par=0b100; // No Parity AVR32_USART0.MR.usart_mode.chrl=0b11; // 8 Data Bits AVR32_USART0.BRGR.cd=13; // Set Baud Rate to 38400 @ 8MHz AVR32_USART0.CR.usart_mode.txen=1; // Activate transmitter } //========================================================================= void Initialise_ADC(void){ // Initialise the ADC // Active Pins PA4(ADCIN0+) and PA19(ADCIN8-) GPIO= 4 & 19 (port 0) function A // Set up the GPIO registers AVR32_GPIO.port[0].gperc=1<<4; // Set to peripheral mode AVR32_GPIO.port[0].gperc=1<<19; // Set to peripheral mode AVR32_GPIO.port[0].puerc=1<<4; // Clear pull-up AVR32_GPIO.port[0].puerc=1<<19; // Clear pull-up // Set PMR2,PMR1,PMR0 to 000 -A AVR32_GPIO.port[0].pmr0c=1<<4; AVR32_GPIO.port[0].pmr1c=1<<4; AVR32_GPIO.port[0].pmr2c=1<<4; // select function A for the mux GPIO register see page 468 AVR32_GPIO.port[0].pmr0c=1<<19; AVR32_GPIO.port[0].pmr1c=1<<19; AVR32_GPIO.port[0].pmr2c=1<<19; // select function A for the mux GPIO register see page 468 //.............. // Program ADC Note values use the underscore... addresses use the . AVR32_ADCIFA.CFG.adcen=0; // Ensure ADC is disabled before setting AVR32_ADCIFA.CFG.shd=1; // No sample and hold (no gain control) AVR32_ADCIFA.CFG.rs=1; // Use 0.6xVDDANA as reference voltage AVR32_ADCIFA.CFG.ssmq=1; // Single sequence mode AVR32_ADCIFA.SEQCFG0.cnvnb=0; // Do 1 conversion only AVR32_ADCIFA.SEQCFG0.sres=1; // 10 bit accuracy AVR32_ADCIFA.ckdiv=3; // Set the clock divide by to 3 to get from 8MHz to <1.5MHz AVR32_ADCIFA.INPSEL00.cnv0=0; // Set Positive pin to ADCIN0 AVR32_ADCIFA.INNSEL00.cnv0=0; // Set Negative pin to ADCIN8 (see page 1147) AVR32_ADCIFA.CFG.adcen=1; // Enable ADC } //========================================================================= void Int_To_Ascii(int X){ // Converts a signed integer number into an ascii array unsigned int Y,Th,T,U,H; Sign='+'; Y=X; if (X < 0) { Y=X*-1; // Effectively 'two's complement - converts to an unsigned value plus sign Sign='-'; } Th=Y/1000; // Calculate the whole number of Thousands, Hundreds, Tens and Units H=Y/100-Th*10; T=Y/10-Th*100-H*10; U=Y-T*10-H*100-Th*1000; ADC[0]=U+48; // Add 48 to the Value to convert it to the correct character and allocate to array ADC[1]=T+48; ADC[2]=H+48; ADC[3]=Th+48; } //========================================================================= void Send_Serial(void){ // Sends ADC numbers over the serial interface // Note a loop is not used as this can sometimes cause delays in program execution AVR32_USART0.THR.txchr=Sign; // Send character while (!(AVR32_USART0.CSR.usart_mode.txrdy & 0b1)) { ; // wait here until buffer empties } AVR32_USART0.THR.txchr=ADC[3]; // Send character while (!(AVR32_USART0.CSR.usart_mode.txrdy & 0b1)) { ; // wait here until buffer empties } AVR32_USART0.THR.txchr=ADC[2]; // Send character while (!(AVR32_USART0.CSR.usart_mode.txrdy & 0b1)) { ; // wait here until buffer empties } AVR32_USART0.THR.txchr=ADC[1]; // Send character while (!(AVR32_USART0.CSR.usart_mode.txrdy & 0b1)) { ; // wait here until buffer empties } AVR32_USART0.THR.txchr=ADC[0]; // Send character while (!(AVR32_USART0.CSR.usart_mode.txrdy & 0b1)) { ; // wait here until buffer empties } AVR32_USART0.THR.txchr=13; // Send carriage return while (!(AVR32_USART0.CSR.usart_mode.txrdy & 0b1)) { ; // wait here until buffer empties } AVR32_USART0.THR.txchr=10; // Send line feed while (!(AVR32_USART0.CSR.usart_mode.txrdy & 0b1)) { ; // wait here until buffer empties } } //=========================================================================
//================================================================================== void Initialise_Timer0(void) { 	// Setup Timer 0   	AVR32_TC0.channel[0].CMR.waveform.wave=1;	// Set to waveform mode		 	AVR32_TC0.channel[0].CMR.waveform.tcclks=1;	// Set to TIMER_CLOCK2 source  (system clock PBC Clock /2)  	AVR32_TC0.channel[0].ra=2000;		// Set counter A0 compare value  	 	AVR32_TC0.channel[0].CCR.clken=1;	// Enable the clock 	AVR32_TC0.channel[0].CCR.swtrg=1;	// Reset and start clock 	 	while(1) { 		AVR32_TC0.channel[0].CCR.swtrg=1;	// Reset and start clock 		while (!(AVR32_TC0.channel[0].SR.cpas) & 0b1 ) {	// Loop until Compare Match occurs 			; 		} 		AVR32_GPIO.port[2].ovrt=1<<18; // Toggle LED on pin PC18 	} } //==================================================================================
EnSol AS R&D and prototyping expertise.
© EnSol AS 2019
Technical Blog

Technical Blog

Specialised R&D equipment is expensive, usually takes many months to arrive, has to be interfaced with, and never quite does what you want it to do! The aim of this blog is to share a few hints and tips on some of the items of equipment and tools we at EnSol have used, and custom built as part of our own R&D work. As this Blog is to complicated for mobile view please have a look in our website format, following are the topics in our website Blog. Qartz Deposition Rate Monitor AVR-32: o Powering up and Getting Started With Ports. o Serial Communications With the USART. o Using the ADC and outputting the data to USART. o Using a timer- A simple time delay.