Driving the TCD1304 with a Nucleo-F401RE

This post from 2015 introduced the very first firmware for driving the tcd1304dg. For an up-to-date version and a more well structured presentation go to tcd1304.wordpress

CCD’s are just like women, demanding but wonderful creatures. And as with women timing is everything with CCD’s.

Here are the timing requirements for the TCD1304:


This, together with the timing diagram in the previous post, is about as much information the datasheet provides. However, these application notes from Toshiba explain the different pulses a little better, and the datasheets for similar chips  – namely the TCD1254 and TCD1103 – are also instructive.

Even though I felt smarter after reading I still had a nagging suspicion it would be a small nightmare to fulfill the timing criteria of the chip.

However, having the Cortex-M4 timers, it proved quite manageable, and after waking up one night remembering an ARM timing register called something-Polarity and only a few trial runs, I finally had this:


The blue line is the SH pulse and the red is the ICG pulse. On two other GPIOs not shown here are the master clock, running at 1.4 MHz, and the ADC clock at 350 kHz. And the MCU itself is doing nothing 🙂

From here it went quickly to this:


It’s my first 1D-selfie! The red line is the ICG-pulse running with a period of 40 ms and the blue is the output from the CCD. The SH is not shown but here it runs with a period of only 400 µs.

Apparently the SH and ICG need only fulfill the requirements when both trigger, and SH does indeed control the integration time. The datasheet finally makes more sense to me (though I still find it confusing that ICG period is called the readout time, when clearly all reading is done 10.6 ms after each ICG pulse).

Here’s a plot of the CCD master clock (running at 1.4 MHz) with the output signal at every 4th clock cycle:


I was hoping to see exactly during which of the four clock cycles the CCD would feed me the output, but I don’t really feel smarter;

As with women there are still many things I don’t quite understand about CCD’s.

Next up is setting up two other pieces of the M4’s peripherals: I need the DMA controller to pick up all those delicious pixelreadings from the ADC.

In the meantime you can enjoy yourself with the source code for driving the TCD1304 with the STM32F401RE Nucleo board. I included a few bits of explanation if you want to play yourself or simply learn more.

Don’t forget to read my posts Programming an ARM-processor (I) and (II) to get a working compiler-environment ready to type make.


5 thoughts on “Driving the TCD1304 with a Nucleo-F401RE

    • I don’t know Arduinos, but if they don’t have timers I think you’ll quickly run into trouble.

      If you go through the source code you will see that the only “work” the MCU actually does is setting up the peripherals (Timers, ADC, SPI and DMA-controllers) and handling an interrupt now and then.

      But to answer your question, no you don’t need the 74HC04, I use it because it’s suggested in datasheet for the TCD1304 for the standard driving circuit. In the source code there are two or three lines in the timer configuration you must change if you don’t have the inverter.


  1. Danny Chan says:

    Your work is great!
    I also wonder how to control timing synchronization of various signals since all clocks are generated by independent timers?
    In code, you mention “TIM3 (fM) and TIM4 (ADC-clock) are not in phase. If you suspect the ADC is reading across two pixels, try and increase TIM2 pulse from 7 to 8. This will shift the pixel readings one period in relation to fM (and 1/4 of a period of the ADC-clock)” But how to guarantee every time the MCU boots up will have the same behavior?


    • The timers are all clocked by APB1, so one timer is not going to wild compared to the others.

      The firmware in this post is of course quite dated. You should (and maybe already did) get the latest from https://tcd1304.wordpress.com/Downloads/

      In the later firmware revisions I’ve taken care to disable/enable the timer-pairs (TIM3/4 and TIM2/5) in a consistent manner to make sure the behaviour is the same. So far I have not seen any deviations when looking at the timing signals on the oscilloscope.

      If you need to be 100% certain of the synchronicity of the timers, there are examples in the standard peripherals library of how to implement this.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s