Sergio Garcìa de Alba Garcin, Gabriel Sanchez Barba, Daniel Torres and Rogelio Gonzalez
For certain applications, the use of a low-cost microcontroller (MCU) is a must, yet many of those applications need to interface with high data rate signals. The problem is that as the data rate of these signals increases, traditional data acquisition approaches are rendered ineffective. The situation is further complicated if the signal has to be over sampled because it may be noisy and/or has high reliability requirements.
For MCUs with a serial parallel interface (SPI) module, such as the Freescale MC68HCxx line of MCUs, it is possible to face these high data rate challenges in an unconventional way. With the technique described in this article very high sampling rates are attainable. In other words, higher typical peak sampling rates are achievable than with traditional approaches that make use of the input capture module, the analog-to-digital converter module, or general purpose I/O pins. In addition, the sampling rate can be varied by changing the configuration of the SPI baud rate generator. This is accomplished by changing the value for the prescaler, clock rate divider, or modifying the bus frequency. Hence, this technique allows for an intelligent implementation that can adjust to changes in signal characteristics.
We developed this SPI sampling solution while working on an application that had critical sampling requirements. The main constraint we faced was to be able to sample and process a high-speed digital signal. Our initial approach was to use a general purpose I/O to sample the signal. The problem with this was that samples were constrained by the speed at which I/O is read and processed by the MCU. The MCU we were using was not able to acquire enough samples to guarantee good accuracy.
Given this scenario, the sampling device should have enough processing capability to perform the required task without any room for error. Since many applications are cost-sensitive, as was our case, using a faster MCU was not an option. Also, due to the inherent high frequency and format of the signal, no conventional solution using any peripheral in our 8-bit MCU could be used. The UART, the analog-to-digital converter, and the GPIO pins were not able to perform this task with the required reliability.
Reliability of the obtained data depends on the number of samples taken from the original signal. According to the Nyquist sampling theorem, the sampling frequency must be greater than N times (at least twice) the input signal bandwidth in order to reconstruct the original signal from the sampled version.
How do you determine the value of N in order to get reliable sampled data? The answer comes from a common sampling technique used in the receiver of a UART; this technique is called bit slicing. It is based on having a clock running 16 times higher than the bit rate, and a counter that is being incremented each clock cycle and is used to sample the incoming data. The counter is started at the beginning of the data frame. The basic approach is to take a sample after eight clock periods, which would be in the middle of the bit. Then the mid-point of each subsequent bit would be sampled every 16 clock cycles. More reliable data would be obtained when sampling each bit not simply once at the mid position, but three times at the mid clock counts (7, 8 and 9). More than three samples can be taken in order to further increase reliability.
After describing the idea of bit slicing, it may seem that a UART can solve the sampling problem. This is not necessarily true, since the UART was designed for sampling a particular data frame. It always looks for high-to-low transitions to start receiving a byte and needs a stop bit at the end of the data frame to finish data sampling.
The approach we used to solve this problem employed the concept of bit slicing, as performed in a UART, but not tied to a specific frame. In this case, the SPI is used to slice bits from the incoming data.
The main purpose of this method is to use the SPI module to sample data. The following section describes in more detail how this technique is used as well as listing the necessary steps that are required to fine-tune and be able to utilize it in different applications and conditions.
1. The SPI module is set as Master with the SPI clock running at its maximum operating frequency. The data to be sampled is fed into the master input pin (MISO). Figure 1 shows the required connections. Sampling a 1-MHz signal with the SPI running at 10-MHz would give 10 samples per data bit. The application should have enough time to read the data from the buffered SPI receive register and store it while the next bit is coming in.
2. To be able to match the bit-timing of the signal to be sampled it is necessary to adjust the MCU's operating frequency. Depending on the platform, it will be necessary to trim the clock (i.e. internal clock, external oscillator/crystal, PLL, etc.). In this case it's necessary to configure the MCU so that 10 SPI clocks equal one bit time for a 1-MHz signal.
3. The third step is to synchronize the start of the SPI transfer with the start of the first bit of the incoming data frame. This is achieved by using an external signal to trigger the event or by having a timed event. This is a critical step since data-sampling is started from this point on. The accuracy of the data will depend on how well synchronized the transfer is to the data-frame being sampled.
4. The next step is to capture the data samples. To do this, a double-buffered SPI module is needed in order to read the previous SPI data as new data is being captured by the SPI. Figure 2 shows how the SPI reads from the MISO pin during every positive edge of the SPI Clock. Every SPI read is equivalent to n data samples of the asynchronous data, where n is the number of bits in the SPI receive buffer. To control the start of each SPI transfer, software cycle timing is used (polling register flags would create too much overhead). The double-buffer to the SPI must be kept full so that one transfer starts immediately after the previous one ends. Using cycle-by-cycle timing and knowledge of when the data becomes available will prevent data overrun. As data is sampled, it is copied from the SPI receive register into a RAM array to be interpreted later. This process is repeated until all data is sampled.
5. To know how many iterations will be required, you need to know the length of the data frame, as well as how many times a bit from the asynchronous data is sampled. If, for example, 32- bit data is expected, and you know that a bit is sampled eight times, then you can conclude that 256 bits (32 bytes) of RAM will be needed to store the sampled data.
6. Once the whole frame is captured, the sampled data may be decoded. The basic idea here is to first segment the sampled data bits into asynchronous data bits. These segments are then analyzed one at a time to determine if the group of bits within each segment make up a logical '1' or '0'. Normally, it is good practice to use some sort of logic (i.e. digital filtering) to get the most reliable reading of each bit. These decoded bits are used to reassemble the original data.
Using the SPI module as described here allows taking maximum advantage of the capabilities of low-end microcontrollers in applications that require sampling and interfacing with high-speed digital signals. The procedure described is versatile and can be adapted to meet the specific requirements of a particular application.
Sergio Garcìa de Alba Garcin is an Applications Engineer at Freescale Semiconductor. He can be reached at [email protected]
Company: FREESCALE SEMICONDUCTOR
Product URL: Click here for more information