i am using stm32 discovery board and using internal ADC in continuous conversion mode. in while(1) loop if i have only one statement to read ADC then the result is correct and i can see the analog value if i change the input. however, if i use any other statement along with ADC read, then the value is not updated.
here is the portion of the code. please share your knowledge.
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
raw = HAL_ADC_GetValue(&hadc1);
voltage = raw / 4096 * 3.0;
HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_13);
HAL_Delay(500);
}
Related
I try to understand when events are generated in Modelica. In the context of functions I noticed behaviour I didn't expect: functions appear to suppress event generation.
I am surprised as this is, to my knowledge, not explicitly stated in the Modelica reference.
For example, if I run this model in OMEdit of OpenModelica 1.17.0
model timeEventTest
Real z(start=0);
Real dummy(start=0);
equation
der(z) = dummy;
algorithm
if time > 10 then
dummy := 1;
else
dummy := -1.;
end if;
end timeEventTest;
I get the following output in the solver window of OMEdit
### STATISTICS ###
timer
events
1 state events
0 time events
solver: dassl
46 steps taken
46 calls of functionODE
44 evaluations of jacobian
0 error test failures
0 convergence test failures
0.000122251s time of jacobian evaluation
The simulation finished successfully.
Apart from the fact that the solver (I used dassl) interpreted the event at time=10 as a state event rather than a time event, the behaviour is as expected.
However, if I instead run the (mathematically identical) model
model timeEventTest2
Real z(start=0);
equation
der(z) = myfunc(time-10);
end timeEventTest2;
with myfunc defined as
function myfunc
input Real x;
output Real y;
algorithm
if x > 0 then
y := 1;
else
y:= -1;
end if;
end myfunc;
I obtain the following output in OMEdit
### STATISTICS ###
timer
events
0 state events
0 time events
solver: dassl
52 steps taken
79 calls of functionODE
63 evaluations of jacobian
13 error test failures
0 convergence test failures
0.000185296s time of jacobian evaluation
The simulation finished successfully.
Not only is the event at time = 10 NOT detected, the solver even got into some trouble as indicated by the error test failures.
This is a trivial example, however, I can imagine that the apparent suppression of events by function may result in mayor problems in larger models.
What did I miss here? Can I enforce the strict triggering of events within functions?
Some built-in functions also trigger events, e.g. div and mod (curiously, sign and abs don't).
Edit: Obviously, you need to run the examples at least to a time > 10s. I ran the simulations to 20s.
Functions in Modelica normally do not generate events.
See 8.5 Events and Synchronization in the Modelica Spec.
All equations and assignment statements within when-clauses and all assignment statements within function classes are implicitly treated with noEvent, i.e., relations within the scope of these operators never induce state or time events.
But its possible to change this behavior:
Add the annotation GenerateEvents=true to the function.
However, it seems like this is not sufficient for some Modelica simulators (tested with OpenModelica v1.16.5 and Dymola 2021x).
To make it work in OpenModelica and Dymola, you have add the Inline annotation or you have to assign the function output in one line.
So if you re-write your function as follows and you will get a state event:
function myfunc
input Real x;
output Real y;
algorithm
y := if x > 0 then 1 else -1;
annotation (GenerateEvents=true);
end myfunc;
or by additionally adding the Inline annotation:
function myfunc
input Real x;
output Real y;
algorithm
if x > 0 then
y := 1;
else
y := -1;
end if;
annotation (GenerateEvents=true, Inline=true);
end myfunc;
State event vs time event
To turn the state event in timeEventTest into a time event, change the if-condition to
if time > 10 then
This is also covered in chapter 8.5 Events and Synchronization of the Modelica Spec. Only the following two cases trigger time events:
time >= discrete expression
time < discrete expression
Goal of the project: To connect an LCD with 8051 as an external memory-mapped I/O device
Problem: Given the following details, my 8051 controller just does not generate an external RD/WR command as required for the rest of the code to work.
Previous work: I used 8051 port 3 pins to generate EN, R/W and RS signals and got it to work. Therefore, I know that my command sequence is working fine. However, this was a really inefficient way of using the LCD because the enable pulse was generated by setting and resetting a port pin. I wish to connect the LCD using the external WR/RD signals and mapping it as a memory-mapped IO device. I have worked through the timing diagrams and the overall block diagram is attached here. As you can see (in the block diagram), the R/W line of LCD is activated using the most significant 6 pins of port 2 so that the LCD gets activated only at the right memory addresses. This operation (implemented in an SPLD) also serves to ensure the delay required at the LCD to ensure the minimum setup time after Port 2 pins 0,1 are used to set inputs at R/W and RS signals of LCD.
Additional hardware info: I have attached a spice diagram to show how the rest of my 8051 is connected. The one thing that is not included there is this: "I use a momentary pushbutton and pull-down resistor for /PSEN, and hold that button when coming out of reset in order to force bootloader operation; then, after the bootloader has started, I release that button to eliminate drive fight issues on the /PSEN line. I use a header/jumper for the /EA input to ensure it is high. Note that if you use these hardware conditions to enter the bootloader when you come out of reset, then the Atmel bootloader is entered regardless of the values of BLJB, BSB, and SBV."
Software used: I am using the paulmon2 to test my code. Programming is done using Flip utility: Flip 3.4.7 through the serial port. A serial emulator program (TeraTerm) is used to communicate with the microcontroller. The microcontroller first executes the paulmon code as well as its extra commands that have been programmed into it before the current user code at 0x2000 location. An extra command allows the user to jump to this code using 'J' command and then giving the address for memory: 0x2000. This calls the current
program and executes it. This is where my code resides and executes from.
The addresses used to map LCD are the following:
LCD_INSTR_WR: 0xA8FF ---> Used to write commands to LCD controller.
This includes all initialization and setup and management commands.
LCD_INSTR_RD: 0xA9FF ---> Used to read command. Done only to read the busy
flag or the current address counter. This is valid only for a single
instruction on the LCD.
LCD_DATA_WR: 0xAAFF ---> Used to write Data to the current address which has
been set either in DDRAM or CGRAM given the LCD_INSTR_WR above.
LCD_DATA_RD: 0xABFF ----> Used to read Data from the current address which
has been set either in DDRAM or CGRAM given the LCD_INSTR_WR above.
The code snippet I write in C to write the external memory:
//Global variables
volatile unsigned char xdata *LCD_INSTR_WR = (char xdata *) 0xA8FF;
volatile unsigned char xdata *LCD_INSTR_RD = (char xdata *) 0xA9FF;
volatile unsigned char xdata *LCD_DATA_WR = (char xdata *) 0xAAFF;
volatile unsigned char xdata *LCD_DATA_RD = (char xdata *) 0xABFF;
/// More code
//Write command example
lcdbusywait();
* LCD_DATA_WR = cc;
Earlier tests one to figure out the problem:
I have tried writing to the memory locations above 2000 using the paulmon memory edit instructions and they write the memory locations alright. Even /WR command is generated in this case as observed (but I have not properly measured/counted the accesses and /WR edge changes.
I have used the logic analyser to confirm that the address (and consequently RS and RW) and data (0x30H command in the beginning) are coming to the ports as expected. ALE is being generated.
I have verified that AUXR register bit EXTRAM is set (AUXR = 0x0E). Also, since EXTRAM is set by default, I tried to remove my initialization code for AUXR completely and that didn’t work either.
I was not sure that the C code that I have written for the XRAM address accesses is correct. However, I went on to check the .asm file and (unless I am neglecting something very minute), the assembly code generated does assign a 0x30h value as immediate data to a register A and uses a “MOVX #dptr,A” instruction to write this value to external memory.
Finally, this is my first post at Stack overflow so the formatting may be off and I do realize this is an extremely long post. Apologies for that. Let me know if you need to see the code files or the compiled hex file or other details. All your help is deeply appreciated.
volatile unsigned char xdata *LCD_INSTR_WR = (char xdata *) 0xA8FF;
I guess LCD_INSTR_WR should have address0xA8FF value.
You can try by using
#define LCD_INSTR_WR XBYTE[0xA8FF]
and then
LCD_INSTR_WR = cc;
or
char xdata LCD_INSTR_WR _at_ 0xA8FF; //This will declare the LCD_INSTR_WR at location 0xA8FF-
You may need to look into the data sheet of the micro controller how to configure extrnal memory
LCD_INSTR_WR = cc;
I want to setup the AD converter at 8KHz rate (for voice sampling).
I know how to do it with timer interrupt.
However I want to set it up directly using DMA..
Operation clock is at 144Mhz (and should be there)--> ADC clock is APB2/2=36Mhz
Now using ADC_SMPR1 I can add 12+480 cycles which is not enough.
Is there any clever way to set the ADC clock down to 8Khz?
In order to use DMA and ADC, you don't reduce the speed of Core or DMA. Mentioned clocks don't affect to sample rate. Sample rate must be set up by timer! But you shouldn't use timer interrupt!
Use the following scheme:
Setup timer on 8KHZ, I suppose you have it but don't enable interrypt!
Set the event to start ADC conversion, for example: hadc.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T3_TRGO;
Confiture timer to master mode by HAL_TIMEx_MasterConfigSynchronization function, example:
TIM_MasterConfigTypeDef master_config = {
.MasterOutputTrigger = TIM_TRGO_UPDATE,
.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE
};
HAL_TIMEx_MasterConfigSynchronization(&hAudioInTim3, &master_config);
Run ADC: HAL_ADC_Start_DMA(&hadc, buffer, size);
Wait for HAL_ADC_ConvCpltCallback event and then process your data.
I try to implement USB CDC FS on the discovery Board from STM. But it is really frustrating.
I created a project via Cube MX with the HAL libraries. At the end I want a data rate near 500 kByte/s. Till now I can see my device in the device manager but really often I cannot open the com port in Hterm. Hterm is only not responding.
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration----------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USB_DEVICE_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
CDC_Transmit_FS(buf, 300);
HAL_Delay(1);
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
I initialise the clocks correctly. Maybe the virtual com port driver cannot buffer the high amount of data they are comeing from the MCU?!
If I increase the delay time in the while loop, sometimes I can open the com port and get the data. The highest data rate I got were about 70 kByte/s. Too less:(
Are there any known bugs in the software? I already increased the heap and stack sizes, but it didn't fix the problem.
Thanks for help,
Check the following two points,
1) Set "wMaxPacketSize" to 64 from 2 (or any value) in USB CDC
device Configuration Descriptor for Endpoint IN Descriptor in
usbd_cdc.c file. The maximum endpoint size for Full speed
usb is 64 bytes.
2) Increase the HCLK and you should see higher data rate.
CDC speed depends on many factors unlike HID where you have
guaranteed data rate. CDC is the fastest if and only if bus is free
with theoretical speed of 1.5 MB/s. I have used STM32F7 disco board
and managed to achieve 500+ KB/s data rate with HCLK 120MHz just a
week ago.
NOTE: Do check the USB clock frequency is set to 48MHz else its
difficult to get it work.
Wish you good luck.
Regards,
Jagadeep.
I have just started to work on this workbench for stellaris 6965. My task is to convert a 5V analog input to digital and light up an LED.
Please tell me how to do it!
The first thing that needs to be done is to read the analog input and obtain the digital value (which will be memorized into one of the ADC registers).
The value you will receive will range between 0 - 1023 (2^8-1), if you use an 8-bit ADC. The exact register where your value will be memorized depends on the analog pin you have the input voltage.
After that, you can compare the value of the register (I recommend memorizing it into a variable first since it's volatile -> it can change at any moment) and set a threshold for lighting the LED. So, if your value is greater than x (where x is your threshold) you set the digital output pin to 1. Otherwise you set it to zero.
The operations described above can be put into the main program loop or in a timer interrupt.