I am trying to use TIM6 on STM32F103C8T6 to generate time and blink an led but the timer doesnt see to be working, what other parameters do i need to initialize in order to be able to use the timer ? code below ?
#include "stm32f10x.h"
int main(void)
{
RCC->APB1ENR |= 0x00000010 ; // CLOCK SIGNAL TO BASIC TIMER 6 IS INITIALIZED
RCC->APB2ENR |= 0x00000004 ; //CLOCK SIGNAL TO GPIO PORT A IS INITIALIZED
GPIOA->CRL |= 0x33333333 ; // LOWER PINS OF GPIO PORT A ARE DEFINED AS PUSH AND PULL OUTPUT
TIM6->CR1 |= 0x0081 ; // COUNTER AND AUTO RELOAD BUFFER ENABLED
TIM6->PSC |= 0x1F40 ; // PRESCALER SET AS 8000
TIM6->ARR |= 0x05DC ; // AUTO RELOAD REGISTER SET AT 1000
while(1)
{
if ( TIM6->CNT == 1000 )
{
GPIOA->BSRR |= 0X0044 ; //SET PINS 2 AND 6 OF GPIOA TO HIGH
}
if ( TIM6->CNT == 0x05DC )
{
GPIOA->BRR |= 0X0044 ; //SET PINS 2 AND 6 OF GPIOA TO HIGH
}
}
}
STM32F103C8T6 has only TIM1 - TIM4, so trying to use TIM6 is doomed to fail. See "Table 4. Timer feature comparison" in the datasheet (page 17).
Related
So i wanted to make a timer on the atmega328p µC using the CTC Modus. The idea was, that every 10milliseconds when the interrupt function is called , in that function i schould increase a variable millisekunden by 10. and once it reaches 1000 it schould be printed out .
The datasheet can be found here: https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf With registers i can change the Mode to the CTC Mode and set up the right Prescaler on the timer.
It is a 16Mhz CPU. So the formula is : T_clock * Prescaler * OCR0A = time( unit is seconds)
So i calculated: (1/ 1610^6) * 1024 * x = 1010^-3(i wanted 10 milli seconds).
and x is then 155.
With the bits CS00 and CS02 i set up the prescaler to 1024. OCR0A was then set to 155 as the formula says. CTC mode was enabled by setting the BIT WGM01. And the last thing was that i increase the variable millisekunden in the interrupt function. For some reason it doesnt want to work. Can anyone pease help me?
#include "Arduino.h"
volatile unsigned long int millisekunden;
unsigned long int last_msg;
char buffer[128];
void setup() {
TCCR0A |= (1 << WGM01); // CTC Modus
TCCR0B |= (1 << CS02) | (1 << CS00); // Prescaler 1024
OCR0A = 155;
// Compare Interrupt
TIMSK0 |= (1 << OCIE0A);
Serial.begin(9600);
}
void loop() {
if (millisekunden - last_msg >= 1000) {
sprintf(buffer, "t=[%lu]", millisekunden);
Serial.println(buffer);
last_msg = millisekunden;
}
}
// Timer-Interrupt-Routine
ISR(TIMER0_COMPA_vect) {
millisekunden = millisekunden + 10;
}
You forgot to globally enable interrupts. Add sei() at the end of setup()
I am using an ATMega2560 with a resistance touch screen (uses the ADC with analogRead commands) – I also use other ADC pins with analogRead (NTC temp sensor). This all works fine.
I have recently added a function that requires me to get ADC readings at known intervals and decided that using the automatic sampling was best – I found the code to do this online and it works well for the function it is required for.
My issue is, after I do the continuous sampling, I cannot get the ADC analogRead values to return the same as they where before the continuous sample.
I have checked the datasheet and it says the initial value for the ADCSRA, ADCSRB & ADMUX = 0 – I have tried this and quite a few other things with no success.
I have attached some code that does the same as my program – i.e. analogRead returns a different value after the continuous sample.
byte samplesADC[100];
int samplesADCCount = 0;
bool ADCEnd = false;
void startADCAcquire(){
int dacChan = 14;
Serial.println("Start ADC Aquire: ");
cli();//diable interrupts
//set up continuous sampling of analog pin 0
//clear ADCSRA and ADCSRB registers
ADCSRA = 0;
ADCSRB = 0;
ADMUX |= dacChan&0x07;
if (dacChan >= 8)
ADCSRB |= _BV(MUX5);
else
ADCSRB &= ~_BV(MUX5);
ADMUX |= (1 << REFS0); //set reference voltage
ADMUX |= (1 << ADLAR); //left align the ADC value- so we can read highest 8 bits from ADCH register only
ADCSRA |= (1 << ADPS2) | (1 << ADPS0); //set ADC clock with 32 prescaler- 16mHz/32=500kHz
ADCSRA |= (1 << ADATE); //enabble auto trigger
ADCSRA |= (1 << ADIE); //enable interrupts when measurement complete
ADCSRA |= (1 << ADEN); //enable ADC
ADCSRA |= (1 << ADSC); //start ADC measurements
sei();//enable interrupts
}
void stopADCAcquire(){
Serial.println("");
Serial.println("Stop ADC Acquire");
cli();//diable interrupts
//set up continuous sampling of analog pin 0
//clear ADCSRA and ADCSRB registers
ADCSRA = 0;
ADCSRB = 0;
ADMUX = 0;
// ADCSRB &= ~_BV(MUX5);
// ADMUX &= ~(1 << ADLAR);
// ADCSRA &= ~(1 << ADSC); // disable adc interrupt
sei();//enable interrupts
}
void setup(){
Serial.begin(9600);
Serial.println("");
Serial.println("START");
Serial.print("Pin A2 (1): ");
Serial.println(analogRead(A2));
startADCAcquire();
int i;
while(ADCEnd == false){
i++;
}
while ((UCSR0A & _BV (TXC0)) == 0)
{}
Serial.print("Pin A2 (2): ");
Serial.println(analogRead(A2));
Serial.println("END");
}
ISR(ADC_vect) {//when new ADC value ready
samplesADC[samplesADCCount] = ADCH;
Serial.print(samplesADC[samplesADCCount]);
Serial.print(", ");
samplesADCCount++;
if(samplesADCCount == 100){
stopADCAcquire();
ADCEnd = true;
}
}
void loop(){
}
Output:
START
Pin A2 (1): 0
Start ADC Aquire:
127, 127, 127...... (x100)
Stop ADC Acquire
Pin A2 (2): 510
END
Thanks #hcheung...
So I'm not sure if you pointed me to the interrupt page, with reference to the code issues around my interrupt handlers - I think I have sorted these by using volatile variables and removing excess code/print statements from the ISR handler. So thanks for the link - it was a helpful reminder.
However this did nothing to resolve my issue and the output remained the same! On the interrupt page I noticed some code where registers are copied to a buffer and then reassigned later. I decided to try this and copied the ADCSRA, ADCSRB & ADMUX registers on program load and reassigned them after the AD scan.
This also failed - Then as last ditch I copied the registers just before the call to start the AD scan (i.e afer analogRead had been called) and it worked. I am now able to use the analogRead command after my continuous read.
I attach updated code that works - i.e analogRead works after being in continuous mode.
volatile byte samplesADC[100];
volatile int samplesADCCount = 0;
volatile bool ADCEnd = false;
uint8_t ADCSRASave;
uint8_t ADCSRBSave;
uint8_t ADMUXSave;
void startADCAcquire(){
int dacChan = 14;
ADCSRASave = ADCSRA;
ADCSRBSave = ADCSRB;
ADMUXSave = ADMUX;
cli();//diable interrupts
//set up continuous sampling of analog pin 0
//clear ADCSRA and ADCSRB registers
ADCSRA = 0;
ADCSRB = 0;
ADMUX |= dacChan&0x07;
if (dacChan >= 8)
ADCSRB |= _BV(MUX5);
else
ADCSRB &= ~_BV(MUX5);
ADMUX |= (1 << REFS0); //set reference voltage
ADMUX |= (1 << ADLAR); //left align the ADC value- so we can read highest 8 bits from ADCH register only
ADCSRA |= (1 << ADPS2) | (1 << ADPS0); //set ADC clock with 32 prescaler- 16mHz/32=500kHz
ADCSRA |= (1 << ADATE); //enabble auto trigger
ADCSRA |= (1 << ADIE); //enable interrupts when measurement complete
ADCSRA |= (1 << ADEN); //enable ADC
ADCSRA |= (1 << ADSC); //start ADC measurements
sei();//enable interrupts
}
void stopADCAcquire(){
cli();//diable interrupts
ADCSRA = ADCSRASave; //0;
ADCSRB = ADCSRBSave; //0;
ADMUX = ADMUXSave; //;
sei();//enable interrupts
}
void setup(){
Serial.begin(9600);
Serial.println("");
Serial.println("START");
Serial.print("Pin A2 (1): ");
Serial.println(analogRead(A14));
Serial.println("Start ADC Aquire: ");
while ((UCSR0A & _BV (TXC0)) == 0){}
startADCAcquire();
while(ADCEnd == false){ }
stopADCAcquire();
for(int x = 0; x < 100; x++){
Serial.print(samplesADC[x]);
Serial.print(", ");
}
Serial.println("");
Serial.println("Stop ADC Acquire");
Serial.print("Pin A2 (2): ");
Serial.println(analogRead(A14));
Serial.println("END");
}
ISR(ADC_vect) {//when new ADC value ready
samplesADC[samplesADCCount] = ADCH;
// Serial.print("p");
samplesADCCount++;
if(samplesADCCount == 100){
ADCEnd = true;
}
}
void loop(){
}
Output:
START
Pin A2 (1): 511
Start ADC Aquire:
127, 127, 127, 127 <<< x 100
Stop ADC Acquire
Pin A2 (2): 511 <<< value now same as first
END
I am using MSO430F2418 for my project. I am sending Hello world message to Bluetooth module via UART pins. Also I need to set pin P2.3 to high to reset the Bluetooth. Unfortunately Im unable to set that perticuler pin to high. When I check the voltage at Reset pin of Bluetooth it is low.
You can see below two lines in my code. I have used these statements to set the P2.3.
P2DIR|=0x08;
P2OUT|=0x08;
I have attached an image. There you can see the hardware. enter image description here
#include <stdio.h>
#include <msp430.h>
const char string[] = { "Hello World\r\n" };
unsigned int i;
int main(void){
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
if (CALBC1_1MHZ==0xFF) // If calibration constant erased
{
while(1); // do not load, trap CPU!!
}
DCOCTL = 0; // Select lowest DCOx and MODx settings
BCSCTL1 = CALBC1_1MHZ; // Set DCO
DCOCTL = CALDCO_1MHZ;
P2DIR|=0x08;
P2OUT|=0x08;
P3SEL = 0x30; // P3.4,5 = USCI_A0 TXD/RXD
UCA0CTL1 |= UCSSEL_3; // SMCLK
UCA0BR0 = 8; // 1MHz 115200
UCA0BR1 = 0; // 1MHz 115200
UCA0MCTL = UCBRS2 + UCBRS1; // Modulation UCBRSx = 5
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
// IE2 |= UCA0RXIE; // Enable USCI_A0 RX interrupt
IE2 |= UCA0TXIE;
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0, interrupts enabled
}
#pragma vector=USCIAB0TX_VECTOR
__interrupt void USCI0TX_ISR(void)
{
UCA0TXBUF = string[i++]; // TX next character
if (i == sizeof string - 1){ // TX over?
IE2 &= ~UCA0TXIE; // Disable USCI_A0 TX interrupt
_delay_cycles(1000000);
i = 0;
IE2 |= UCA0TXIE; // Enable USCI_A0 TX interrupt
}
}
I've adjusted the example from here for the STM3240G-EVAL board in order to blink LEDs 3 and 4. I have it working, but am confused by the Mode register setting:
GPIOG->MODER |= (GPIO_MODER_MODER6_0 | GPIO_MODER_MODER8_0) ;
When I read the reference manual (p186), it claims that the mode must be set to 01 for output, yet setting it to 0 in this way works just fine. Ideally I'd like to be able to change to the other modes, but I would have assumed that the above code would have changed pins 6 and 8 of port G to input pins. I must be missing something.
Here's my complete main document in case it's relevant:
#include "stm32f4xx.h"
/* We will use PG6 and PG8 connected to LEDs 1 and 2 because they're the same port. */
/* Find base register value for Port G */
void delay (int a);
int main(void)
{
/*!< At this stage the microcontroller clock setting is already configured,
this is done through SystemInit() function which is called from startup
file (startup_stm32f0xx.s) before to branch to application main.
To reconfigure the default setting of SystemInit() function, refer to
system_stm32f0xx.c file
*/
/* GPIOG Periph clock enable */
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOGEN;
GPIOG->MODER |= (GPIO_MODER_MODER6_0 | GPIO_MODER_MODER8_0) ;
/* Configure PG6 and PG8 in output mode */
GPIOG->OTYPER &= ~(GPIO_OTYPER_OT_6 | GPIO_OTYPER_OT_8) ;
// Ensure push pull mode selected--default
GPIOG->OSPEEDR |= (GPIO_OSPEEDER_OSPEEDR6|GPIO_OSPEEDER_OSPEEDR8);
//Ensure maximum speed setting (even though it is unnecessary)
GPIOG->PUPDR &= ~(GPIO_PUPDR_PUPDR6|GPIO_PUPDR_PUPDR8);
//Ensure all pull up pull down resistors are disabled
while (1)
{
/* Set PG6 and PG8 */
/* the bit set/reset low register SETS the output data register */
/* the bit set/reset high register RESETS the output data register */
GPIOG -> BSRRL = (1 << 6);
GPIOG -> BSRRL = (1 << 8);
delay(500000);
/* Reset PC8 and PC9 */
GPIOG -> BSRRH = (1 << 6);
GPIOG -> BSRRH = (1 << 8);
delay(500000);
}
return 0;
}
void delay (int a)
{
volatile int i,j;
for (i=0 ; i < a ; i++)
{
j++;
}
return;
}
You aren't setting it to zero, you're setting it to one.
The definition of the GPIO_MODER_MODER6_0 constant is 0x00001000. The mask for the GPIO_MODER_MODER6 bits is 0x00003000, so you're putting bits 01 into the right place.
If the constant GPIO_MODER_MODER6_0 were defined as zero, then or'ing it into the configuration register would have no effect in any case. To set both bits to zero you'd need to do something like:
GPIOG->MODER &= ~(GPIO_MODER_MODER6_0 | GPIO_MODER_MODER6_1);
The _0 and _1 suffixes refer to the bit numbers for masking, not the values being written.
I am trying to create a simple program that reads RTC clock value and prints it to serial monitor. USART is working fine, but i can't figure out what's wrong with RTC. It is giving me all the time same value that was set in setuRTC(). Also the second interrupt is not working either. Edit: I am using STM32f1 development board, same as this
Here is my RTC setup:
void setupRTC(void){
RCC->APB1ENR |= (RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN); //Enable the power and backup interface clocks by setting the PWREN and BKPEN bitsin the RCC_APB1ENR register
PWR->CR |= PWR_CR_DBP; //Enable access to the backup registers and the RTC.
RCC->BDCR |= RCC_BDCR_LSEON; //External Low Speed oscillator enable
while((RCC->BDCR & RCC_BDCR_LSERDY) == 0); //Wait until external oscillisator is stabilised
RCC->BDCR |= RCC_BDCR_RTCSEL_LSE;
sendstr(textlse);
RCC->BDCR |= RCC_BDCR_RTCSEL_LSE; //Select Source (LSE oscillator clock used as RTC clock )
RCC->BDCR &= ~((1 << 8) | (1 << 9)); //Unusable clock source, here to prevent warnings, turn off clock sources to RTC.
RCC->BDCR = RCC_BDCR_RTCEN; //RTC clock enable
RTC->CRL &= ~RTC_CRL_RSF; //Clear registers Synchronized Flag
while(!(RTC->CRL & RTC_CRL_RSF)); //Wait for the RSF bit in RTC_CRL to be set by hardware
while((RTC->CRL & RTC_CRL_RTOFF) == 0); //Wait for RTOFF It is not possible to write to the RTC_CR register while the peripheral is completing a previous write operation
RTC->CRL |= RTC_CRL_CNF; //Set the CNF bit to enter configuration mode
/* Set RTC COUNTER MSB word */
RTC->CNTH = (12*3600 + 40*60 + 00) >> 16; //Random time
/* Set RTC COUNTER LSB word */
RTC->CNTL = ((12*3600 + 40*60 + 00)& 0x0000FFFF);
RTC->CRH |= RTC_CRH_SECIE; //Second Interrupt Enable
RTC->CRL &= ~RTC_CRL_CNF; //Exit configuration mode
while((RTC->CRL & RTC_CRL_RTOFF) == 0); //Wait for RTOFF
sendstr(textconf);
}
Here is the whole program:
#include "stm32f10x.h"
#include <stdio.h>
uint8_t text[] = {"\nSTM32 USART test ä ö \n"};
uint8_t textlse[] = {"LSE ready\n"};
uint8_t textconf[] = {"Configuration complete\n"};
char str[32]; // buffer for text
uint8_t RxBuffer[1024];
int rxcount = 0;
// Private function prototypes
void sendstr(uint8_t * str);
void sendChar(uint8_t ch);
void sendTime(uint32_t ch);
void setupRTC(void);
void setupUSART(void);
u32 rtc_get_counter_val(void);
void setupRTC(void){
RCC->APB1ENR |= (RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN); //Enable the power and backup interface clocks by setting the PWREN and BKPEN bitsin the RCC_APB1ENR register
PWR->CR |= PWR_CR_DBP; //Enable access to the backup registers and the RTC.
RCC->BDCR |= RCC_BDCR_LSEON; //External Low Speed oscillator enable
while((RCC->BDCR & RCC_BDCR_LSERDY) == 0); //Wait until external oscillisator is stabilised
RCC->BDCR |= RCC_BDCR_RTCSEL_LSE;
sendstr(textlse);
RCC->BDCR |= RCC_BDCR_RTCSEL_LSE; //Select Source (LSE oscillator clock used as RTC clock )
RCC->BDCR &= ~((1 << 8) | (1 << 9)); //Unusable clock source, here to prevent warnings, turn off clock sources to RTC.
RCC->BDCR = RCC_BDCR_RTCEN; //RTC clock enable
RTC->CRL &= ~RTC_CRL_RSF; //Clear registers Synchronized Flag
while(!(RTC->CRL & RTC_CRL_RSF)); //Wait for the RSF bit in RTC_CRL to be set by hardware
while((RTC->CRL & RTC_CRL_RTOFF) == 0); //Wait for RTOFF It is not possible to write to the RTC_CR register while the peripheral is completing a previous write operation
RTC->CRL |= RTC_CRL_CNF; //Set the CNF bit to enter configuration mode
/* Set RTC COUNTER MSB word */
RTC->CNTH = (12*3600 + 40*60 + 00) >> 16; //Random time
/* Set RTC COUNTER LSB word */
RTC->CNTL = ((12*3600 + 40*60 + 00)& 0x0000FFFF);
RTC->CRH |= RTC_CRH_SECIE; //Second Interrupt Enable
RTC->CRL &= ~RTC_CRL_CNF; //Exit configuration mode
while((RTC->CRL & RTC_CRL_RTOFF) == 0); //Wait for RTOFF
sendstr(textconf);
}
void setupUSART(void){
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_USART1EN;
USART1->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE;
USART1->BRR = (SystemCoreClock / 115200);
GPIOA->CRH &= 0xFFFFF00F; //Set RX(PA10) and TX(PA9) pins
GPIOA->CRH |= 0x000008A0; //In TTL communication, TX pin must be conficured as pushpull
NVIC_EnableIRQ(USART1_IRQn);
USART1->CR1 |= USART_CR1_RXNEIE; //Enable USART interrupt
}
int main(void)
{
vu32 dly;
uint32_t time;
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN; //Enable clock for PC pins
GPIOC->CRL &= 0x00FFFFFF; //Setup PC6 and PC6 leds
GPIOC->CRL |= 0x33000000;
setupUSART();
setupRTC();
sendstr(text);
while (1)
{
time = rtc_get_counter_val();
sprintf(str, "%10d\n", time);
sendstr(str);
for(dly = 0; dly < 1000000; dly++);
}
}
void sendChar(uint8_t ch){
while(!(USART1->SR & USART_SR_TXE));
USART1->DR = ch;
}
void sendTime(uint32_t ch){
while(!(USART1->SR & USART_SR_TXE));
USART1->DR = ch;
}
void sendstr(uint8_t * str){
while(*str != 0){
sendChar(*str);
str++;
}
}
void USART1_IRQHandler(void){
if(USART1->SR & 0x0020){ //content of the shift register is transferred to the RDR RXNE bit.
GPIOC->BSRR = (1 << 7);
RxBuffer[rxcount++] = (uint8_t)(USART1->DR & (uint8_t)USART_DR_DR);
USART1->SR = (uint16_t)~0x0020;
sendstr(RxBuffer);
}
}
void RTC_IRQHandler(void){
if(RTC->CRL & RTC_CRL_SECF){
GPIOC->BSRR = (1 << 7);
RTC->CRL &= ~RTC_CRL_SECF;
}
}
u32 rtc_get_counter_val(void)
{
return (RTC->CNTH << 16) | RTC->CNTL;
}
Mayby too late but the problem is that you do not set any clock source to the RTC.
The following lines need to be swapped, from:
RCC->BDCR |= RCC_BDCR_RTCSEL_LSE;
RCC->BDCR &= ~((1 << 8) | (1 << 9));
to:
RCC->BDCR &= ~((1 << 8) | (1 << 9));
RCC->BDCR |= RCC_BDCR_RTCSEL_LSE;
The way it was before you first set correctly the clock source, and then cleared again the bits, leaving the RTC without clocking.